ZFでRESTfulに挑戦

挑戦というか、それっぽく。

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を設定して、サブディレクトリ以下でも正しくルーティング出来るようになったらしいけど、その辺は未確認。

ネタが無いので、アプリはなしです。

プロフィール

このブログ記事について

このページは、koshigoeが2006年11月28日 14:40に書いたブログ記事です。

ひとつ前のブログ記事は「VOXに登録してみた」です。

次のブログ記事は「Zend_Http_Client#getは?がつくんだね」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。