Laravel良いのだけど、ちょっとしたもの作るのに使うのはデカイよなー。でも、0から書くのもめんどうだなー。と、そんな気分に完全にマッチするフレームワーク Slimを使ってみた。
Slimとはどんなフレームワークなのか。
“Slim is a PHP micro framework” と、README.markdownの書き出しにも有る様に、microである事を意識して作られた小さなフレームワークです。 元ソースが分からないのですが、Sinatraにインスパイアされて作ったらしいです。
ドキュメントもたった15項目しかありません。。
- GETTING STARTED
- CONFIGURATION
- ROUTING
- ENVIRONMENT
- REQUEST
- RESPONSE
- VIEW
- HTTP CACHING
- MIDDLEWARE
- HOOKS
- FLASH MESSAGES
- SESSIONS
- LOGGING
- ERROR HANDLING
- DEPENDENCY INJECTION
小さくあるために、機能をそぎ落としているのが特徴です。そのため、中規模〜大規模なアプリケーション開発には向いていません。
開発者のインタビュー記事が面白かった。
Hello World
何はともあれHello World. してみる。
例によってcomposerを使ってインストール可能なので、一歩目が非常に楽ちん。
composer.json を用意し、composer install
を実行。
{
"require": {
"slim/slim": "2.*"
}
}
vendor ディレクトリと同列に index.phpを配置。
<?php
require 'vendor/autoload.php';
$app = new \Slim\Slim();
$app->get('/hello/:name', function($name){
echo 'Hello, ', $name;
});
$app->run();
php -S localhost:8080
としてとりあえず動かしてみると…
http://localhost:8080/hello/senta で Hello, senta と表示されます。
ルーティング
Slimは、HTTPメソッド(GET, POST, PUT, DELETE, OPTIONS などなど)と、pathを組み合わせてルーティングを行います。 これによって、RESTアーキテクチャに沿ったURLの設計/実装が簡単に実現できます。
マッピング
基本的なHTTPメソッドは、\Slim\Slim
クラスに実装されており、各HTTPメソッドと同名のメソッドに対してURI
とcallback
を渡す事でマッピングします。
<?php
$app = new \Slim\Slim();
$app->post('/path/:id, function ($id) {
// 何か処理
});
これで /path/1 へPOSTリクエストに対するマッピングが完了。
:var
等としてURIに値を含める事ができ、その値はコールバックの引数として渡されます。
コールバックの返り値は基本的に必要ありませんが、false
を返すと404と扱われるもよう。
リクエストパラメータ
リクエストパラメータや、リクエストヘッダーの取得は、$app->request
オブジェクトから取得できます。
$app = new \Slim\Slim();
$app->map('/hello, function($name) use ($app){
// $_GET['hoge']を取得する
var_dump($app->request->get('hoge'));
// $_POST['fuga']を取得する
var_dump($app->request->post('fuga'));
// $_REQUEST 的なやつ
print_r($app->request->params());
// HTTPメソッドがPOSTか否か
var_dump($app->request->isPost());
})->via('GET', 'POST');
などなど。
HTTP メソッドオーバーライド
HTML formのmethodアトリビュートは、GET/POSTにしか対応していないため、Slimアプリケーション内でPUTやDELETE等に変更する必要があります。
これもよくあるフレームワーク同様、_METHOD
パラメータを使って対応できます。
<form action="/books/1" method="post">
<input type="hidden" name="_METHOD" value="PUT"/>
....
</form>
HTML form以外では、X-HTTP-Method-Override
ヘッダーにて指定する事でうまいことルーティングしてくれます。
レスポンス
Hello, Worldでは、単純にecho
を使って出力していました。
これに加え、TwigやSmartyを使ったテンプレートからの出力や、JSONの出力を行う為のAPIが用意されています。
テンプレート (View)
テンプレートを使う場合、$app->config('templates.path')
にてテンプレートのパスを設定します。
デフォルトでは、./templates
になっています。
テンプレートパスにhello.phtml
を置き、
<!-- hello.phtml -->
<body>
<h1>Hello, <?php echo $name ?></h1>
</body>
アプリケーション内で$app->render()
を呼び出します。
// index.php
$app->get('/hello/:name', function($name) use ($app){
$app->render('hello.phtml', array("name" => $name));
});
JSON
JSON出力は適切なヘッダーと、JSON文字列が必要。
ヘッダーは、$app->response->headers->set()
にて行い、JSON文字列はjson_encode
を使います。
$app->get('/hello/:name', function($name) use ($app){
$user = array("name" => $name);
$app->response->headers->set('Content-Type', 'application/json');
$app->response->setBody(json_encode($user));
});
全てのルーティングにheaders->set()
を書くのはイマイチなので、ルーティングの外でヘッダーをセットする事も可能。
$app = new \Slim\Slim();
$app->response->headers->set('Content-Type', 'application/json');
プロジェクトが大きくなってきたら…?
と、まぁここまで分かればあとはテキトーに実装できそう。
ただ、このSlimで実装したサービスやツールが成長していくと、index.phpのroute
がどんどん肥大化していきます。。
そんな時にどのように整理すれば良いのか…本家ブログに例がありました。
先ずディレクトリレイアウト。
public_html/
.htaccess
index.php
app/
routes/
api.php
admin.php
vendor/
lib/
このようにroutes/
ディレクトリにひとまとまりのルーティング郡を別ファイルで分け、それぞれをindex.phpで読み込む。それだけ。
<?php
$app = new Slim();
require '../app/routes/api.php';
require '../app/routes/admin.php';
// ....
$app->run();
ちょっと抵抗を感じる方法ですが…一応整理は可能。。 (LaravelやZendなどのフレームワークの様な、Controllerベースの実装はあえて実装していないらしいです。)