EC-CUBE4の開発環境をVagrantで作ったときに遅いので何とかする

EC-CUBE3でプラグインを作っていたのだけれども、EC-CUBE4が出ちゃった。
なのでそろそろ勉強しようかなと重い腰を上げてVagrantでローカルに環境を構築したんですけども、それが激遅で。。。

最近はDockerで環境作る機会が多いようなのですが、まぁVagrantもね、それなりに好きなんですよ。
結論から言うと、Vagrantのローカル環境が激遅だったのはcacheファイルを保存するディレクトリがsynced_folderに含まれているからなんですけどもね。
ほんでもって、cacheが一度できれば、動きは結構早いですよ。
なので、EC-CUBE4がすごく遅いとかそういうわけではなく、私の環境構築に問題があるということで予めご承知おきを。

あと、まだ環境を構築しただけのぺーぺーなので、EC-CUBEの解釈とか間違っていたらごめんなさいね。

## EC-CUBE3のときはどうしてた？
EC-CUBE3のときは、Kusanagiでローカル環境を構築しており、このときはsynced_folderにcacheディレクトリなどが含まれていても割と早かったんですよ。

今回はなんとなくCentOS7.4上に普通にLAMP環境を構築したら、まぁ遅い。
Dockerを使ったりsynced_folderのtypeをrsyncにしたらいんだろうけど、まぁ何かの役に立てばと思いましてとりあえず記事を起こしてみました。

## OPCacheを入れる

EC-CUBE4はPHP7.1.3のバージョンがシステム要件としてあるので、PHPのバージョンを上げて高速化を図る必要はないのですが、初め環境構築の際にOPCacheを入れ忘れておりました。
なので、まずOPCacheを入れました。

## xdebugを停止

初めからxdebugを入れなければいい話なのですが、もし入れていたら停止しておきましょうということですね。

## cacheフォルダの変更

初めにも記載しましたが、これが一番のネック。
ソースを確認したところ ``` src\Eccube\Kernel.php ``` のKernelクラスにベタ書きされている模様。
リリース後は特に問題ないのですが、開発時はこれをsynced_folder外に移動させたいなぁと思いまして。

というわけで、開発用とう位置づけで`AppKernelクラス`と`index_dev.php`を作ることにしました。

EC-CUBE3のときは、開発時には初めからindex_dev.phpが用意されており、このファイルにアクセスすることで、デバッグモードの開発ができていたのですが、EC-CUBE4からは環境変数や.envなどでデバッグモードに指定する方式に変わっていました。

### AppKernelの作成

今回は、Kernelクラスのcacheの吐き出し先だけを変えたかったのでKernelを継承して作成。
↓こんな感じ。ファイルの場所は、`app\Customize`配下

```php:AppKernel.php
namespace Customize;

use Eccube\Kernel;

class AppKernel extends Kernel
{

    public function getCacheDir()
    {
        // この辺のパスはsynced_folder以外であれば適当に
//        return $this->getProjectDir().'/var/cache/'.$this->environment;
        return sys_get_temp_dir() . '/var/cache/' . $this->environment;
    }

    public function getLogDir()
    {
        // ログはそこまで影響しないので、ご自由に。
        return $this->getProjectDir().'/var/log';
//        return sys_get_temp_dir() . '/var/log';
    }


}
```

ほんで、これをindex_dev.phpでコールする

### index_dev.php の作成

index_dev.php はindex.phpのほぼコピー。
置き場所は、index.phpと同じディレクトリ。

```php:index_dev.php
<?php

use Dotenv\Dotenv;
use Symfony\Component\Debug\Debug;
use Symfony\Component\HttpFoundation\Request;

// システム要件チェック
if (version_compare(PHP_VERSION, '7.1.3') < 0) {
    die('Your PHP installation is too old. EC-CUBE requires at least PHP 7.1.3. See the <a href="http://www.ec-cube.net/product/system.php" target="_blank">system requirements</a> page for more information.');
}

$autoload = __DIR__.'/vendor/autoload.php';

if (!file_exists($autoload) && !is_readable($autoload)) {
    die('Composer is not installed.');
}
require $autoload;

// The check is to ensure we don't use .env in production
if (!isset($_SERVER['APP_ENV'])) {
    if (!class_exists(Dotenv::class)) {
        throw new \RuntimeException('APP_ENV environment variable is not defined. You need to define environment variables for configuration or add "symfony/dotenv" as a Composer dependency to load variables from a .env file.');
    }

    if (file_exists(__DIR__ . '/.env')) {
        (new Dotenv(__DIR__))->overload();

        if (strpos(getenv('DATABASE_URL'), 'sqlite') !== false && !extension_loaded('pdo_sqlite')) {
            (new Dotenv(__DIR__, '.env.install'))->overload();
        }
    } else {
        (new Dotenv(__DIR__, '.env.install'))->overload();
    }
}


// 開発用なので環境変数に関係なくデバッグモードに。
//$env = isset($_SERVER['APP_ENV']) ? $_SERVER['APP_ENV'] : 'dev';
//$debug = isset($_SERVER['APP_DEBUG']) ? $_SERVER['APP_DEBUG'] : ('prod' !== $env);
$env = 'dev';
$debug = 1;

if ($debug) {
    umask(0000);

    Debug::enable();
}

$trustedProxies = isset($_SERVER['TRUSTED_PROXIES']) ? $_SERVER['TRUSTED_PROXIES'] : false;
if ($trustedProxies) {
    Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST);
}

$trustedHosts = isset($_SERVER['TRUSTED_HOSTS']) ? $_SERVER['TRUSTED_HOSTS'] : false;
if ($trustedHosts) {
    Request::setTrustedHosts(explode(',', $trustedHosts));
}

$request = Request::createFromGlobals();

if (file_exists(__DIR__.'/.maintenance')) {
    $pathInfo = \rawurldecode($request->getPathInfo());
    $adminPath = env('ECCUBE_ADMIN_ROUTE', 'admin');
    $adminPath = '/'.\trim($adminPath, '/').'/';
    if (\strpos($pathInfo, $adminPath) !== 0) {
        $locale = env('ECCUBE_LOCALE');
        $templateCode = env('ECCUBE_TEMPLATE_CODE');
        $baseUrl = \htmlspecialchars(\rawurldecode($request->getBaseUrl()), ENT_QUOTES);

        header('HTTP/1.1 503 Service Temporarily Unavailable');
        require __DIR__.'/maintenance.php';
        return;
    }
}

# ここでAppKernelをnew!
$kernel = new \Customize\AppKernel($env, $debug);

$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
```

あとは、アクセスのときにEC-CUBE3のときと同様にindex_dev.phpを指定するだけ。
` https://example.com/index_dev.php `

とまぁ、ここまで書いたわけですが、index_dev.phpでアクセスした場合に全ての機能に問題ないかどうかまでは確認していないので、使えなかったらごめんなさーいね。

あと、***本番サーバー等に間違ってリリース***しないようにご注意を。

## console も何とかする

実は、cacheのディレクトリをsynced_folder以外にしようと思った理由は、consoleコマンドを使った際に、Noteメッセージで注意されたからなんですよね。

```sh
[vagrant@eccube4 eccube4]$ ./bin/console eccube:plugin:uninstall --code=HogeHoge

 // Clearing the cache for the dev environment with debug true

 ! [NOTE] For better performances, you should move the cache and log directories to a non-shared
 !        folder of the VM.

 [OK] Cache for the "dev" environment (debug=true) was successfully cleared.

 [OK] Installed.
```

というわけで、consoleも別途作成します。
``` app\bin\```というディレクトリを作成し、その配下にconsoleファイルを作成

```php:console
#!/usr/bin/env php
<?php

use Eccube\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Debug\Debug;

umask(0000);
set_time_limit(0);

# ↓ここら辺のパス
require __DIR__.'/../../vendor/autoload.php';

if (!class_exists(Application::class)) {
    throw new \RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.');
}

if (!isset($_SERVER['APP_ENV'])) {
    # ↓ここら辺のパス
    if (file_exists(__DIR__.'/../../.env')) {
        (new Dotenv())->load(__DIR__.'/../../.env');
    } else {
        (new Dotenv())->load(__DIR__.'/../../.env.install');
    }
}

$input = new ArgvInput();
$env = $input->getParameterOption(['--env', '-e'], $_SERVER['APP_ENV'] ?? 'dev');
$debug = ($_SERVER['APP_DEBUG'] ?? true) !== '0' && !$input->hasParameterOption(['--no-debug', '']);

if ($debug && class_exists(Debug::class)) {
    Debug::enable();
}

# ↓ここ
$kernel = new \Customize\AppKernel($env, $debug);
$application = new Application($kernel);
$application->run($input);

```

で、アクセスするときは app配下のconsoleを指定

```sh
[vagrant@eccube4 eccube4]$ ./app/bin/console eccube:plugin:install --code=HogeHoge

 // Clearing the cache for the dev environment with debug true

 [OK] Cache for the "dev" environment (debug=true) was successfully cleared.

 [OK] Installed.
```

とまぁ、こんな感じで。

## EC-CUBE4になっていろいろ変わった

まぁ、とりあえず現時点でした高速化の対応は以上です。
また何かあれば追記するかもしれないです。

EC-CUBE4を、まだ触り始めたばかりですが、プラグインの作成方法とか結構変わっていました。
ベースの考え方などは変わらないのですが、書き方がそれなりに。。

今はEC-CUBE3に慣れていた影響で戸惑いのほうが多いですが、きっと慣れたらEC-CUBE4の開発のほうが捗りそうと感じております。
あと、そもそもの管理画面の機能などが大幅に改善されているのも良いですね。

最近は、BASEなどわざわざ開発しなくても安くて便利で先進的なASPサービスが多い中、EC-CUBE4がどのくらい盛り上がるかはわかりませんが、一定の需要もあることは確かなので、地道に勉強していきたいなと。

さぁて頑張ろうかな。