挑戦というか、それっぽく。
Zend_Controller_RewriteRouterのマニュアルを読んでいたら、URLからactionを隠せるし、事前に定義してパラメータを変数名無しでルーティング(?)出来るとの事なので、じゃあRESTfulな感じでいけるかな、と。
正しいアプローチかは怪しすぎながら、Zend_Controller_RewriteRouterを使ってみたかったのでとりあえず。
以下、index.php
<?php require_once realpath(dirname(__FILE__) . '/../conf/init.php'); require_once 'Zend/Controller/Front.php'; require_once 'Zend/Controller/RewriteRouter.php'; // setup route $router = new Zend_Controller_RewriteRouter(); $map = 'test/:var1/:var2'; $default = array( "var1" => 1, "var2" => "hoge", "controller" => "test", "action" => "index" ); $rule = array( "var1" => '\d+', "var2" => '\w+' ); $route = new Zend_Controller_Router_Route($map, $default, $rule); $router->addRoute("test", $route); // setup controller $ctrl = Zend_Controller_Front::getInstance(); $ctrl->setRouter($router); // run Zend_Controller_Front::run(SYSDIR . '/app/controllers'); ?>
マニュアルでは、Zend_Controller_RewriteRouter#addRouteの引数が文字列とか配列とかで渡せるっぽい書き方なんだけど、trunkから持って来たバージョンではZend_Controller_Router_Routeを通してオブジェクトとして渡さないと駄目みたい。この引数の順序は、マップ/デフォルト/フィルタ(それぞれ呼び方は自己流)。コントローラとアクションをデフォルトで設定しておかないとnoRouteになるっぽい。
以下、コントローラ。
<?php require_once dirname(__FILE__) . '/Test/Action.php'; require_once 'Restful/Router.php'; class TestController extends Zend_Controller_Action { public function indexAction() { $obj = new Test_Action($this->_getAllParams()); $router = new Restful_Router(); $router->register('get', array($obj, 'show')); $router->register('post', array($obj, 'create')); $router->register('put', array($obj, 'update')); $router->register('delete', array($obj, 'delete')); $router->routing(); } public function noRouteAction() { header('HTTP/1.x 404 Not Found'); exit; } } ?>
indexアクションで全て処理。Restful_RouterってのでHTTP_REQUEST_METHOD{GET|POST|PUT|DELETE}に従って関数を呼び出す。これは自作。関数呼び出しの登録に使っているTest_Actionは単純にプリントしてるだけ(パラメータのダンプもだけど)。
以下、Restful_RouterとTest_Action
<?php /** * Routing by HTTP Request Method {GET|POST|PUT|DELETE} * * @author Koshigoe <KoshigoeBushou@gmail.com> */ class Restful_Router_Exception extends Exception { } class Restful_Router { private $routingMap; public function __construct() { $this->routingMap = array( "get" => null, "post" => null, "put" => null, "delete" => null ); } /** * register routing map * * @param String $method {get, post, put, delete} * @param Mixed $obj routing function * @return Boolean */ public function register($method, $function) { if (!in_array($method, array_keys($this->routingMap))) { return false; } if (empty($function)) { return false; } if (is_array($function)) { if (count($function) < 2) { return false; } if (empty($function[0]) or empty($function[1])) { return false; } if (!is_object($function[0])) { return false; } $this->routingMap[$method] = array($function[0], strval($function[1])); } else { $this->routingMap[$method] = $function; } return true; } /** * routing */ public function routing() { if (empty($_SERVER["REQUEST_METHOD"])) { throw new Restful_Router_Exception("HTTP Method was empty."); } $method = strtolower($_SERVER["REQUEST_METHOD"]); if (!in_array($method, array_keys($this->routingMap))) { throw new Restful_Router_Exception("HTTP Method was invalid."); } if (empty($this->routingMap[$method])) { throw new Restful_Router_Exception("No route."); } $map = $this->routingMap[$method]; if (!is_array($map)) { $map(); } else { $obj = $map[0]; $fnc = $map[1]; $obj->$fnc(); } } } ?>
<?php class Test_Action { public function __construct($params) { $this->params = $params; } public function show() { echo "show"; echo "<pre>"; var_dump($this->params); echo "</pre>"; } public function create() { echo "create"; echo "<pre>"; var_dump($this->params); echo "</pre>"; } public function update() { echo "update"; echo "<pre>"; var_dump($this->params); echo "</pre>"; } public function delete() { echo "delete"; echo "<pre>"; var_dump($this->params); echo "</pre>"; } } ?>
ソースを貼ってはいるけど、これで何が出来るわけでもなく、これだけで動くわけでもなく。まあ、ZFでもURLをきれいに書けるようになってるね、と。ベースURLを設定して、サブディレクトリ以下でも正しくルーティング出来るようになったらしいけど、その辺は未確認。
ネタが無いので、アプリはなしです。

