CakePHP3の初期インストールと環境切り分けプラグインを使った本番反映

このシリーズは、CakePHP3 系で web サイトを開発する一連の流れの解説になります。初回である本記事は、ローカルの開発環境でサイトを新規作成し、web サーバへ反映するまでの手順になります。重要なファイルは git の管理下から除外しつつ、特別なデプロイツールを使わずに単に git pull して反映します。また、これを叶えるために plugin を利用します。

ローカル作業
普段開発で使用している Vagrant / VertualBox を利用してアプリケーションの開発の準備を行います。仮想環境が立ち上がったらアプリケーションを作成します。

http://book.cakephp.org/3.0/ja/installation.html#cakephp

アプリケーションのインストール

公式マニュアルに従って composer でアプリケーションをインストールします。まずは composer.phar のダウンロードです。私は以下ディレクトリに移動して実行しました。

cd /usr/share/nginx/html/サイト名

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

composer.phar がダウンロードされるので、ダウンロード完了後に公式マニュアル通りにコマンドを打ってアプリケーションを作成しました。

php composer.phar create-project --prefer-dist cakephp/app app

すると、/usr/share/nginx/html/サイト名/app 以下に色んなファイルが作成されるかと思います。作成完了後、app ディレクトリ以下を git のバージョン管理下に入れます。なお、デフォルトで /vendor/*, /tmp/*, /logs/* は gitignore に記載されていますので、これら以外を管理下に入れます。

# app ディレクトリ以下に作成されたファイルをバージョン管理に追加
# デフォルトで /vendor/*, /tmp/*, /logs/* は gitignore に記載されており、引き続き除外する
/usr/share/nginx/html/サイト名/app

app ディレクトリと同じ階層にある composer.phar を削除し、app 直下に composer.phar を新しくダウンロードします。こんなことをしなくても最初からうまくできるのかもしれませんが、公式マニュアルのインストール方法に従いつつプラグインのインストールの準備を行うため、app 直下に composer.phar を配置しました。なお、単にファイルを移動させるよりも新しくダウンロードしなおす方がトラブルなく無難です。

rm /usr/share/nginx/html/サイト名/composer.phar
cd /usr/share/nginx/html/サイト名/app

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

ダウンロードが完了したら、gitignore に composer.phar を追記します。app ディレクトリ以下、composer 関連は composer.json, composer.lock, composer.phar の3つがあり、composer.phar のみバージョン管理から除外します。以下この時点での .gitignore の内容になります。

/vendor/*
/config/app.php
/tmp/*
/logs/*

composer.phar

いったんここで初期コミットとして git commit しました。ここでコミットしておき、今後何かミスをした時に元に戻れるようにしました。

環境切り分け用のプラグインの利用

開発環境 / 本番環境の環境切り替えを行うために、プラグインを利用します。今回利用するプラグインの開発者は CakePHP の開発者なので信頼性は抜群です。

https://github.com/josegonzalez/cakephp-environments

インストール手順に従って composer.json の内容を書き換えます。

# 最後に1行追加
{
    "require": {
        "php": ">=5.6",
        "cakephp/cakephp": "3.4.*",
        "mobiledetect/mobiledetectlib": "2.*",
        "cakephp/migrations": "~1.0",
        "cakephp/plugin-installer": "~1.0",
        "josegonzalez/cakephp-environments": "3.0.0"
    }
}

json のよくあるミスとして「 , 」に注意して記述します。記述が完了したら app ディレクトリ以下に移動して、下記コマンドでプラグインをインストールします。インストールが完了すると composer.lock ファイルが変更されます。

cd /usr/share/nginx/html/サイト名/app
php composer.phar update

config/bootstrap.php 内、Plugin::loadAll(); を記述してプラグインを入れるたびにファイルを書き換える手間を省きます。都度ファイルを書き換えても問題ありませんし、これはご自身のルールに従えばいいかなと思います。Plugin::loadAll(); はデフォルトでコメントアウトされているので、私はこれをコメント解除しました。

/*
 * Plugins need to be loaded manually, you can either load them one by one or all of them in a single call
 * Uncomment one of the lines below, as you need. make sure you read the documentation on Plugin to use more
 * advanced ways of loading plugins
 *
 * Plugin::loadAll(); // Loads all plugins at once
 * Plugin::load('Migrations'); //Loads a single plugin named Migrations
 *
 */
Plugin::loadAll();

インストールが完了したら、プラグインの公式マニュアルに従って各々ファイルを作成します。今回はステージング環境を省き、本番環境と開発環境の設定ファイル、及び各環境を読み込み実行するファイルを作成しました。

# 作成したファイル
app/config/environments.php
app/config/environments/development.php
app/config/environments/production.php

CakePHP2 系の時と同様、マニュアルには環境ファイルを切り分ける処理が書いていないので、私はサーバ変数を利用して切り分ける処理を environments.php に記述しました。なお、CAKE_ENV は production, development ファイル内の $name と同じ値にします。

# app/config/environments.php の内容
use Josegonzalez\Environments\Environment;

if(file_exists(dirname(__FILE__) . DS . 'environments' . DS . 'production.php')) {
    include dirname(__FILE__) . DS . 'environments' . DS . 'production.php';
}
include dirname(__FILE__) . DS . 'environments' . DS . 'development.php';

Environment::start(env('CAKE_ENV'));

各々のファイルを作成し終えたら、本番環境の極秘情報を記述した production.php は git 管理したくないので ignore に追加します。この時点での .gitignore ファイルの内容です。

/vendor/*
/config/app.php
/tmp/*
/logs/*

composer.phar
/config/environments/production.php

追加完了後、app.php から Security.salt とDBの接続情報を各種環境ファイルにそれぞれ移植し、.gitignore から app.php を除外してバージョン管理下に配置します。なお、Security.salt の値は開発環境と本番環境で別々の値にすることを強くお勧めします。早くサーバに反映して開発 / 本番環境の行き来を楽しみたいので、私は以下のみ移植しました。例として development.php の内容を記します。

# app/config/environments/development.php の内容
 true,
        'Security.salt' => env('SECURITY_SALT', 'ランダム文字列'),
        'Datasources.default.host'=> 'localhost',
        'Datasources.default.username'=> 'my_app',
        'Datasources.default.password'=> 'secret',
        'Datasources.default.database'=> 'my_app',
        'Datasources.test.host'=> 'localhost',
        'Datasources.test.username'=> 'my_app',
        'Datasources.test.password'=> 'secret',
        'Datasources.test.database'=> 'test_myapp',
    ]
);
# app/config/app.php の内容、以下を削除

# 12 行目あたりを削除
'debug' => filter_var(env('DEBUG', true), FILTER_VALIDATE_BOOLEAN),

# 66 - 68 行目あたりを削除
'Security' => [
    'salt' => env('SECURITY_SALT', 'ランダム文字列'),
],

# 232 - 234, 272 - 274 行目あたりを削除
'Datasources' => [
    'default' => [
            :
        //以下を削除
        'username' => 'my_app',
        'password' => 'secret',
        'database' => 'my_app',
            :
        ],
        'test' => [
            :
        //以下を削除
        'username' => 'my_app',
        'password' => 'secret',
        'database' => 'test_myapp',
            :
        ],
# .gitignore の内容
/vendor/*
/tmp/*
/logs/*

composer.phar
/config/environments/production.php

Datasources の情報をこのプラグインで切り替えるため、bootstrap.php 内、Configure::load の記述のすぐ下でenvironments.php を include し、Configure::read や Configure::consume で期待通りに動くようにします。私は最初、何も考えずに適当な位置で読み込み、environment プラグインがうまく動作しない!と一人で騒いでしまいました。environments.php ファイル内で Environment::start() を実行しているので、bootstrap.php に記述する場所を間違えると Configure::consume でデフォルトの情報が消えてしまいます。

try {
    Configure::config('default', new PhpConfig());
    Configure::load('app', 'default', false);
} catch (\Exception $e) {
    exit($e->getMessage() . "\n");
}

# ここに記述
include dirname(__FILE__) . DS . 'environments.php';

/*
 * 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');

くどいですが、production.php が管理から除外されていることを確認して、git commit & push します。

本番環境の作業
ディレクトリに移動してファイルを展開します。また、composer を実行してプラグインをインストールします。

cd /usr/share/nginx/html
git clone 'your repository url'
//appディレクトリ以下に composer.phar をダウンロードしてプラグインをインストール
cd 'your repository'/app
curl -s 'https://getcomposer.org/installer' | php
php composer.phar install

インストールが完了したら、nginx の設定ファイルに CAKE_ENV の値を追加し、プラグインが自動で環境を切り替えるように設定します。CakePHP3 の公式マニュアルの内容に加えたものが下記になります。

location ~ \.php$ {
	try_files	$uri =404;
	include		/etc/nginx/fastcgi_params;
	fastcgi_pass	127.0.0.1:9000;
	fastcgi_index	index.php;
	fastcgi_param	SCRIPT_FILENAME $document_root$fastcgi_script_name;
	fastcgi_param	CAKE_ENV production;
}

修正が完了したら、nginx をリロードして内容を反映します。

nginx -t
systemctl reload nginx.service

これで web からアクセスされた場合に環境を切り分けられますが、コマンド操作(bake や migration 等)では対応できません。そこで、以下を .bashrc に記載します。なお、場所はユーザのホームディレクトリにあります。

cd ~/
vim .bashrc
//以下記載する内容
export CAKE_ENV=production

これで開発 / 本番環境の行き来が完了しました。が、本番環境の url にアクセスすると NotFound のエラーが発生しました。急いで作業したので、Templete/Pages/home.ctp がデフォルトのままで、このまま本番環境に反映するとエラーが発生するようにテンプレートに記述されていました。

Please replace Pages/home.ctp with your own version.
「Error: The requested address ‘/’ was not found on this server.」

なんて親切なと思う一方、NotFound じゃないエラーにして欲しいなと思いつつテンプレートを修正して、問題ないことを確認しました。これで環境を行き来しつつ重要ファイルはバージョン管理から除外されたかと思います。

終わりに
何か不明点があれば、サイト TOP のお問い合わせよりご質問ください。また、より CakePHP3 について詳しく知りたい方は、現在公式マニュアルの翻訳を行っていますので一緒にやりませんか?

CakePHP3 の公式マニュアルを翻訳する方法

Enjoy!!