Zend公式のPSR-7対応マイクロフレームワーク「zend-expressive」を使ってみようと思い、
Google App Engine にインストールしたので、備忘メモです。
インストールした zend-expressive のバージョンは、1.0.0 です。
--2016.06.10追記 start--
この記事の内容を踏まえて、
別記事「zend-expressive-skeletonをGoogleAppEngine/PHP向けにカスタマイズ」
で、簡単にインストールできるカスタマイズ版スケルトンを用意しました。
--2016.06.10追記 end--
skeleton をインストール
動作確認しやすいように、スケルトンをインストールします。
テンプレートエンジンを「Plates」にした以外は、デフォルトのままです。
$ composer create-project zendframework/zend-expressive-skeleton <project dir>
Minimal skeleton? (no default middleware, templates, or assets; configuration only)
[y] Yes (minimal)
[n] No (full; recommended)
Make your selection (No):
Which router do you want to use?
[1] Aura.Router
[2] FastRoute
[3] Zend Router
Make your selection or type a composer package name and version (FastRoute):
Which container do you want to use for dependency injection?
[1] Aura.Di
[2] Pimple
[3] Zend ServiceManager
Make your selection or type a composer package name and version (Zend ServiceManager):
Which template engine do you want to use?
[1] Plates
[2] Twig
[3] Zend View installs Zend ServiceManager
[n] None of the above
Make your selection or type a composer package name and version (n): 1
Which error handler do you want to use during development?
[1] Whoops
[n] None of the above
Make your selection or type a composer package name and version (Whoops):
project dir の直下に app.yaml を追加
Google App Engine に必要な設定ファイルです。
とりあえず、サンプル画面を表示できる程度の設定にしました。
module: default
version: 1
runtime: php55
api_version: 1
handlers:
- url: /favicon.ico
static_files: public/favicon.ico
upload: public/favicon.ico
- url: /zf-logo.png
static_files: public/zf-logo.png
upload: public/zf-logo.png
- url: /.*
script: public/index.php
ローカル環境で動作確認(失敗)
参考: https://cloud.google.com/appengine/docs/php/quickstart#test_the_application
恒例のSDKで動作確認してみます。
$ dev_appserver.py <project dir>
ブラウザで、localhost:8080 にアクセスしてみると。
すわ fatal error です。
Catchable fatal error: Argument 1 passed to Zend\ServiceManager\Config::__construct() must be of the type array, null given, called in /Users/shuhei/Documents/src/googleAppEngine/phpzend/config/container.php on line 11 and defined in /Users/shuhei/Documents/src/googleAppEngine/phpzend/vendor/zendframework/zend-servicemanager/src/Config.php on line 65
config/autoload 配下の定義ファイルを glob することができずに困っているようです。
Load configuration for Google App Engine
定義ファイルの読み込みは、config/config.php で行っていますが、問題点は以下の2点です。
- glob()関数を使っている
- 定義ファイルの内容をキャッシュする際の出力先がファイル (file_put_contents)
Google App Engine向けの読み込み処理を作成しました。
- glob()関数を opendir()/readdir()関数に変更
- キャッシュ出力先を、ファイルからMemcacheへ変更
以下の内容を
config/config-gae.php
として、配置します。
<?php
use Zend\Stdlib\ArrayUtils;
/**
* Configuration files are loaded in a specific order. First ``global.php``, then ``*.global.php``.
* then ``local.php`` and finally ``*.local.php``. This way local settings overwrite global settings.
*
* The configuration can be cached. This can be done by setting ``config_cache_enabled`` to ``true``.
*
* Obviously, if you use closures in your config you can't cache it.
*/
$cachedConfigKey = 'cache_app_config';
$mc = new Memcached();
// Try to load the cached config
if(!($config = $mc->get($cachedConfigKey))) {
if ($mc->getResultCode() == Memcached::RES_NOTFOUND) {
$config = [];
}
$confdir = __DIR__ . '/autoload';
if ($handle = opendir($confdir)) {
$pattern = '/(global|local)\.php$/';
$files = [];
while (false !== ($file = readdir($handle))) {
if (preg_match($pattern, $file) === 1) {
$fn = implode('.', array_reverse(explode('.', $file)));
$files[] = $fn;
}
}
asort($files);
foreach($files as $file) {
$fn = implode('.', array_reverse(explode('.', $file)));
$config = ArrayUtils::merge($config, include $confdir.'/'.$fn);
}
closedir($handle);
}
// Cache config if enabled
if (isset($config['config_cache_enabled']) && $config['config_cache_enabled'] === true) {
$mc->set($cachedConfigKey, $config);
}
}
// Return an ArrayObject so we can inject the config as a service in Aura.Di
// and still use array checks like ``is_array``.
return new ArrayObject($config, ArrayObject::ARRAY_AS_PROPS);
呼び出し元の
config/container.php
を編集します。
// Load configuration
//$config = require __DIR__ . '/config.php';
$config = require __DIR__ . '/config-gae.php';
ローカル環境で動作確認(成功)
SDKのWebサーバが自動的にリロードしてくれるので、
ブラウザをリロードすれば、正常に表示されるはずです。
app_config.php の最後に記載しているように、
エラー画面テンプレートも用意されているので、404 Not Foundの画面も表示できます。
デプロイ
参考: https://cloud.google.com/appengine/docs/php/quickstart#deploy_your_app
https://console.developers.google.com/
で、プロジェクトを作成して、該当のプロジェクトIDに向けてデプロイしましょう。
$ appcfg.py -A YOUR_PROJECT_ID update app.yaml
http://(YOUR_PROJECT_ID).appspot.com/
今後、開発を進める上でどのような問題が出るか分かりませんが、ひとまず第一歩、完了です。