こんにちは Slim PHP framework

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/sentaHello, senta と表示されます。

ルーティング

Slimは、HTTPメソッド(GET, POST, PUT, DELETE, OPTIONS などなど)と、pathを組み合わせてルーティングを行います。
これによって、RESTアーキテクチャに沿ったURLの設計/実装が簡単に実現できます。

マッピング

基本的なHTTPメソッドは、\Slim\Slimクラスに実装されており、各HTTPメソッドと同名のメソッドに対してURIcallbackを渡す事でマッピングします。

<?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ベースの実装はあえて実装していないらしいです。)

SHOTA

I'm WEB developer

Tokyo, Japan http://senta.me/