「最速」PHPフレームワークPhalconのルーティングについて、基本事項をまとめます(公式ドキュメントの翻訳+αです)。記事執筆時のPhalconのバージョンは1.3.1です。

基本形

<?php

// ルーターオブジェクトを作成
$router = new \Phalcon\Mvc\Router();

// ルーティング定義
$router->add(
    "/admin/users/my-profile",
    array(
        "controller" => "users",
        "action"     => "profile",
    )
);

\Phalcon\Mvc\Router::add()でルーティングを定義します。第1引数にURL、第2引数にコントローラーやアクションを定義します。なお、ルーティングの優先順位は、後にadd()したものが優先されます。

ルーティングの動作確認

Phalconがインストールされ有効になっている環境であれば、以下のようなスクリプトでルーティングの動作確認を行えます。

<?php

$router = new \Phalcon\Mvc\Router();

$router->add(
    "/admin/users/my-profile",
    array(
        "controller" => "users",
        "action"     => "profile",
    )
);

// テストしたいURLを指定
$router->handle("/admin/users/my-profile");

// コントローラ名とアクション名を表示
printf("Controller: %s \n", $router->getControllerName());
printf("Action    : %s \n", $router->getActionName());

// ルーティングオブジェクトの中身全部表示
$route = $router->getMatchedRoute();
var_dump($route);

このスクリプトを実行すると、handle()で指定したURLに対して、ルーターに定義したルートがマッチしたかどうか、マッチした場合はどのコントローラーとアクションが実行されるか、が分かります。

柔軟なルーティング

プレースホルダーを使うことで、柔軟なルートを定義できます。

$router->add(
    "/admin/:controller/a/:action/:params",
    array(
        "controller" => 1,
        "action"     => 2,
        "params"     => 3,
    )
);

このルートが定義されているとき、/admin/users/a/delete/dave/301 にアクセスすると、以下のように解釈されます。

Controllerusers
Actiondelete
Parameterdave
Parameter301

プレースホルダー

\Phalcon\Mvc\Routerで使用可能なプレースホルダーについてまとめた表が以下になります。

プレースホルダー 正規表現 用途
/:module /([a-zA-Z0-9_-]+) モジュール名
/:controller /([a-zA-Z0-9_-]+) コントローラ名
/:action /([a-zA-Z0-9_]+) アクション名
/:params (/.*)* パラメータ。スラッシュ区切りで複数渡せる。このプレースホルダーはルートの末尾にのみ使用できる。
/:namespace /([a-zA-Z0-9_-]+) 名前空間名
/:int /([0-9]+) 自然数

なお、コントローラー名は大文字化が行われます。この際、_と-は取り除かれます。例えば、some_controller は、 SomeController に変換されます。

名前付きパラメータ

$router->add(
    "/news/([0-9]{4})/([0-9]{2})/([0-9]{2})/:params",
    array(
        "controller" => "posts",
        "action"     => "show",
        "year"       => 1, // ([0-9]{4})
        "month"      => 2, // ([0-9]{2})
        "day"        => 3, // ([0-9]{2})
        "params"     => 4, // :params
    )
);

上のようにルーティングを定義すると、下のような形でURLからパラメータを受け取れます。

<?php

class PostsController extends \Phalcon\Mvc\Controller
{
    public function showAction()
    {
        $year  = $this->dispatcher->getParam("year");
        $month = $this->dispatcher->getParam("month");
        $day   = $this->dispatcher->getParam("day");
    }
}

以下のような書き方もできます。

$router->add(
    "/documentation/{chapter}/{name}.{type:[a-z]+}",
    array(
        "controller" => "documentation",
        "action"     => "show"
    )
);
<?php

class DocumentationController extends \Phalcon\Mvc\Controller
{
    public function showAction()
    {
        $name = $this->dispatcher->getParam("name");
        $type = $this->dispatcher->getParam("type");
    }
}

短縮形

\Phalcon\Mvc\Router::add()の第2引数には、配列ではなく文字列を渡すこともできます(短縮形)。この場合、コントローラ名とメソッド名を指定します。

// 短縮形
$router->add("/posts/{year:[0-9]+}/{title:[a-z\-]+}", "Posts::show");

// 配列
$router->add(
    "/posts/([0-9]+)/([a-z\-]+)",
    array(
       "controller" => "posts",
       "action"     => "show",
       "year"       => 1,
       "title"      => 2,
    )
);

モジュールへのルーティング

URLにモジュール名が含まれている場合は以下のようなルーティングを行います(複数モジュール構成の場合に使用します)。

$router->add('/:module/:controller/:action/:params', array(
    'module' => 1,
    'controller' => 2,
    'action' => 3,
    'params' => 4
));

このルートが定義されている時、/admin/users/edit/sonny にアクセスすると、以下のように解釈されます。

Moduleadmin
Controllerusers
Actionedit
Parametersonny

モジュール名を明示的に指定することもできます。

$router->add("/login", array(
    'module'     => 'backend',
    'controller' => 'login',
    'action'     => 'index',
));

$router->add("/products/:action", array(
    'module'     => 'frontend',
    'controller' => 'products',
    'action'     => 1,
));

名前空間を指定することもできます。

$router->add("/:namespace/login", array(
    'namespace'  => 1,
    'controller' => 'login',
    'action'     => 'index'
));

名前空間とクラス名の指定もできます。

$router->add("/login", array(
    'namespace' => 'Backend\Controllers',
    'controller' => 'login',
    'action' => 'index'
));

HTTPメソッドの制限

add()でルートを定義した場合、全てのHTTPメソッドが許可されます。特定のメソッドに限定したい場合は、addGet()/addPost()等を使用します。また、複数のHTTPメソッドを指定する場合は、via()を使用します。

// GETのみ
$router->addGet("/products/edit/{id}", "Products::edit");

// POSTのみ
$router->addPost("/products/save", "Products::save");

// POST又はPUT
$router->add("/products/update")->via(array("POST", "PUT"));

パラメータの加工

$router
    ->add('/search/{postcode:[a-z\-]+}', array(
        'controller' => 'search',
        'action'     => 'show'
    ))
    ->convert('postcode', function($slug) {
        // - を取り除く
        return str_replace('-', '', $slug);
    });

この例では、/search/100-6010 にアクセスすると、searchコントローラーのshowメソッドに、「1006010」というパラメーターが渡されます。

続きは(2)で

今回は、基本的なルーティングの定義方法について紹介しました(公式ドキュメントの、Using convertionsまで)。 次回は、Groups of Routesから先、ルーティングをまとめて管理する方法等をみていきます。