2016年9月24日土曜日

Phalcon を使ってみた

Phalconは「A full-stack PHP framework delivered as a C-extension」というフレームワークです。
ベンチマークで超絶速度(PHPフレームワークにおいて)をたたき出すポテンシャルを持っています。
Phalcon 公式はこちら

Phalcon、PHPビルトインサーバーでも動作するってよ

Phalconの公式ドキュメントはかなり詳細なことまで書かれています。
もちろん、サーバー設定方法まで丁寧に記載されています。
で、PHP5.4から搭載されたPHPビルトインサーバーの設定も書かれていました。
PHP ビルトインサーバーの利用
この設定は .htrouter.php というファイル(.htaccess的なもの)で、これを行わないとPhalconのデフォルトと同一の設定になりません。
 
<?php
if (!file_exists(__DIR__ . '/' . $_SERVER['REQUEST_URI'])) {
    $_GET['_url'] = $_SERVER['REQUEST_URI'];
}
return false;
 
このファイルを使用してサーバーを起動
php -S localhost:8000 -t /public .htrouter.php
これで.htrouter.phpを使用してサーバーへアクセするようになります。

ところがどっこい

さて、これを使用していたもののタイトル通りにここではまってしまいました。
例えばGETにクエリ(パラメーター、Query String…等呼ばれ方はいろいろ)を付与し “/foo/bar?baz=qux” というURLへアクセスすると、ルーティングが上手く動作しなくなります。
変数などをダンプしてみると、
“bar?baz=qux” という文字列がルーティングの判定時に使われています。
本来この時点で取得しなければいけないのは “bar” という文字列だけです。
Phalconのルーティングは、ControllerクラスのActionと呼ばれる関数を使用して動的に呼び出しています。
上記の場合、bar?baz=quxAction()みたいな呼ばれ方をしてしまうということです。
本当はbarAction()を呼ばなければならない。

ならば正せばいい

実際のところ、このことが全く分からず(むしろ勝手にクエリストリングが分割されると思い込んでいたのも問題だった)、1日ハマって見つけたサイトがこちら。
Route not matches URI with querystring · Issue #379 · phalcon/cphalcon
ハイ、公式のgithubのissuesでした。
このissueを読んで上記のルーティングの仕組みをやっと理解。
出来上がった .htrouter.php はこちら
 
<?php
if (!file_exists(__DIR__ . '/' . $_SERVER['REQUEST_URI'])) {
    if (!empty($_SERVER['REQUEST_URI'])) {
       $uriParts = explode('?', $_SERVER['REQUEST_URI']);
       $uri = $uriParts[0];
    } else {
       $uri = '/';
    }
    $_GET['_url'] = $uri;
}

return false;

このポイントの記事が全く見つからず、きっとPHP ビルトインサーバーをみんなが使ってないだけ俺の知識が浅いんじゃないうんきっとそうに違いない。と自己弁護しつつPhalconライフをお楽しみたいと思います。
追伸: 実はvar_dumpで$_GETとかを見ていればヒントがあった。困ったときはvar_dump。