setDefaultModule() の挙動

Phwittr に向けてまずはディレクトリ構成から練るかと思い、色々やってたら気持ち悪い現象にブチあたった。


Zend Framework にはモジューラ・ディレクトリという概念がある。
http://framework.zend.com/manual/ja/zend.controller.modular.html


デフォルトではこんな感じにルーティングされる
modules 以下に各モジュールがあり、その下にコントローラがあるとする。


で、/modules/default というディレクトリを他のディレクトリ名に変更することが出来る。

<?php
$front = Zend_Controller_Front::getInstance();
$front->setDefaultModule('index');

$front->dispatch() をする前に setDefaultModule() で index ディレクトリを指定してやると、以下のようにルーティングされた。

-> /index/controllers/HogeController.php の indexAction

-> /default/controllers/IndexController.php の hogeAction


下の二つが期待した結果と異なった。
なんで?と思い検索したら、とれっくかいはつ さんに以下のようにあった。

ルーティングの変更前は、次のURLでルーティング可能です。

http://サンプル/default/:controller/:actoin

http://www.trekdevel.net/archives/122

default の時は、省略されてるという事か。
つまり、setDefautMoudle('default') と指定した場合、http://example.com/index/hogehttp://example.com/default/index/hoge と同じ。
で、デフォルトだから、省略した書き方が出来る。
setDefaultModule() で指定されたディレクトリは全て同じようになると思ったけど・・・。
仕様なんか、不具合なんかが分からん・・・。
issue tracker みても module 関係のレポートが多すぎて、追いきれないw

解決策?

とりあえずルーティングを設定してやれば、解決する見たい。

<?php
// $defaultModule = 'index';
$defaultModule = 'default';
$router = $front->getRouter();
// removeDefaultRoutes() を記述しない場合はデフォルトのに上書き
$router->removeDefaultRoutes();
$route = new Zend_Controller_Router_Route(
    ':controller/:action/*',
    array(
        'module' => $defaultModule,
        'controller' => 'index',
        'action' => 'index'
    )
);
$router->addRoute($defaultModule, $route);

コントローラに以下のように書いた

<?php
class IndexController extends Zend_Action_Controller
{
    public function indexAction()
    {
        var_dump('index');
        var_dump($this->_getAllParams();
    }
    public function hogeAction()
    {
        var_dump('hoge');
        var_dump($this->_getAllParams();
    }
}

結果

$front->setDefaultModule('default'); の場合

http://example.com/index/
string 'index' (length=5)
array
  'controller' => string 'index' (length=5)
  'module' => string 'default' (length=7)
  'action' => string 'index' (length=5)

http://example.com/index/hoge
string 'hoge' (length=4)
array
  'controller' => string 'index' (length=5)
  'action' => string 'hoge' (length=4)
  'module' => string 'default' (length=7)

http://example.com/index/index/hoge
string 'index' (length=5)
array
  'controller' => string 'index' (length=5)
  'action' => string 'index' (length=5)
  'hoge' => string '' (length=0)
  'module' => string 'default' (length=7)

$front->setDefaultModule('index'); の場合

http://example.com/index
string 'index' (length=5)
array
  'controller' => string 'index' (length=5)
  'module' => string 'index' (length=5)
  'action' => string 'index' (length=5)
  
http://example.com/index/hoge
string 'hoge' (length=4)
array
  'controller' => string 'index' (length=5)
  'action' => string 'hoge' (length=4)
  'module' => string 'index' (length=5)

http://example.com/index/index/hoge
string 'index' (length=5)
array
  'controller' => string 'index' (length=5)
  'action' => string 'index' (length=5)
  'hoge' => string '' (length=0)
  'module' => string 'index' (length=5)

期待通りの結果になった。
$front->setDefaultModule(); なんてそうそう変更する訳でもないから、害はないっちゃないけど、気持ち悪ったので。。。


# 2008/5/9 追記
上記のパターンのみだと、モジュールごとにルーティングの設定を行わないと行けない。
例えば http://example/admin のように admin モジュールにアクセスしたいと思った場合、上記の場合だと、admin コントローラを探しに行く。
admin モジュールを見に行きたい場合は、admin モジュールのルーティングを行う必要がある。
わざわざルーティングしなくて済むような方法を模索中・・・。