CakePHP3をHerokuで動かす設定


## composer.json に heroku-buildpack-php を追加する。

```json
    "require-dev": {
        "psy/psysh": "@stable",
        "cakephp/debug_kit": "~3.0",
        "cakephp/bake": "~1.0",
        "heroku/heroku-buildpack-php": "*"
    },
```

## Procfileを作成する。

```Procfile
web: vendor/bin/heroku-php-apache2 webroot/
```

## Herokuの環境変数

Herokuの環境変数に `CAKE_ENV=heroku` を追加する。

```bash
$ heroku config:add CAKE_ENV="heroku"
```

## Heroku環境用の app.php を読み込む設定

先に追加した環境変数 `CAKE_ENV=heroku` が設定されている場合だけ、`app.php` をオーバーライドする `app_heroku.php` を読み込むようにする。

```bootstrap.php
try {
    Configure::config('default', new PhpConfig());
    Configure::load('app', 'default', false);
} catch (\Exception $e) {
    die($e->getMessage() . "\n");
}
// Load an environment local configuration file.
// You can use a file like app_local.php to provide local overrides to your
// shared configuration.
//Configure::load('app_local', 'default');
if (isset($_ENV['CAKE_ENV'])) {
    Configure::load('app_' . $_ENV['CAKE_ENV'], 'default');
}
```

## デバッグモードの設定

false にしておく。

```app_heroku.php
    'debug' => false,
```

## SALTの設定

Herokuの環境変数に `SALT` を追加し、`app_heroku.php`に設定する。

```bash
$ heroku config:add SALT="1234567890987654321"
```

```app_heroku.php
    'Security' => [
        'salt' => env('SALT'),
    ],
```

## キャッシュの設定

デフォルトだとローカルファイルを使うようになっているので、Memcachedを使うようにする。

```bash
$ heroku addons:add memcachier
```

```app_heroku.php
    'Cache' => [
        'default' => [
            'className' => 'Memcached',
            'prefix' => 'myapp_cake_',
            'servers' => [env('MEMCACHIER_SERVERS')],
            'username' => env('MEMCACHIER_USERNAME'),
            'password' => env('MEMCACHIER_PASSWORD'),
            'duration' => '+1440 minutes',
        ],

        'session' => [
            'className' => 'Memcached',
            'prefix' => 'myapp_cake_session_',
            'servers' => [env('MEMCACHIER_SERVERS')],
            'username' => env('MEMCACHIER_USERNAME'),
            'password' => env('MEMCACHIER_PASSWORD'),
            'duration' => '+1440 minutes',
        ],

        '_cake_core_' => [
            'className' => 'Memcached',
            'prefix' => 'myapp_cake_core_',
            'servers' => [env('MEMCACHIER_SERVERS')],
            'username' => env('MEMCACHIER_USERNAME'),
            'password' => env('MEMCACHIER_PASSWORD'),
            'duration' => '+1 years',
        ],

        '_cake_model_' => [
            'className' => 'Memcached',
            'prefix' => 'myapp_cake_model_',
            'servers' => [env('MEMCACHIER_SERVERS')],
            'username' => env('MEMCACHIER_USERNAME'),
            'password' => env('MEMCACHIER_PASSWORD'),
            'duration' => '+1 years',
        ],
    ],
```

## セッションの設定

デフォルトだとローカルファイルになっているので、先に設定したMemcachedを使うようにする。

```app_heroku.php
    'Session' => [
        'defaults' => 'cache',
        'handler' => [
            'config' => 'session'
        ]
    ],
```

## ログの設定

デフォルトだとローカルファイルにログを出力するようになっているので、標準出力に出力するように変更する。ログエンジンに`ConsoleLog`を使う。

```app_heroku.php
    'Log' => [
        'debug' => [
            'className' => 'Cake\Log\Engine\ConsoleLog',
            'stream' => 'php://stdout',
            'levels' => ['notice', 'info', 'debug'],
        ],
        'error' => [
            'className' => 'Cake\Log\Engine\ConsoleLog',
            'stream' => 'php://stderr',
            'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'],
        ],
    ],
```

## MySQLの設定

ClearDBアドオンの環境変数で`mysql://[username]:[password]@[host]/[database]?reconnect=true`という形式でMySQLの接続先URLが得られるので、`parse_url()`で分解してDatasourcesに設定する。

```bash
$ heroku addons:add cleardb
```

```app_heroku.php
$db = parse_url(env('CLEARDB_DATABASE_URL'));
return [
      :
    'Datasources' => [
        'default' => [
            'className' => 'Cake\Database\Connection',
            'driver' => 'Cake\Database\Driver\Mysql',
            'persistent' => false,
            'host' => $db['host'],
            'username' => $db['user'],
            'password' => $db['pass'],
            'database' => substr($db['path'], 1),
            'encoding' => 'utf8',
            'timezone' => 'UTC',
            'cacheMetadata' => true,
            'quoteIdentifiers' => false,
        ],
    ],
```