2007-06-06 [長年日記]
_ 起動ファイルのコードのスコープ
どうでもいいけど、ちょっと気になること。
Zend Frameworkでは、起動ファイルにいろいろ初期化コードを書いていくけど、そこで使った変数はグローバル変数になってしまうことになる。たとえば、
$config = new Zend_Config_Xml('/path/to/config.xml');
Zend_Registry::set('config', $config);
とかして読み込んだconfigオブジェクトは、普通はZend_Registryにセットしておいて、必要に応じてZend_Registry::get('config')して使うけれども、実際はアクションコントローラの中とかで、
global $config;
とかすればアクセスできてしまう。かといって、わざわざ、
$config = new Zend_Config_Xml('/path/to/config.xml');
Zend_Registry::set('config', $config);
unset($config);
とまでは書かないよね。
じゃあグローバルスコープじゃないようにしようかと、起動ファイルの中身を、
function main()
{
// 各種初期化処理
}
main();
とかmain()関数でくくって書けばいいかなーと思ったりしたんだけど、それもいまいちぱっとしない気がする。どうせなら、
class Application
{
public function __construct()
{
$this->_init();
$this->_run();
}
protected function _init()
{
//初期化コード
}
protected function _run()
{
//実行
}
}
new Application();
までやっちゃった方が融通が利くか(staticメソッドのみで書いて、インスタンス化させずに動かした方がきれいか)。
っつーか、起動ファイルの中身をグローバルスコープでフラットに書いていると、可読性が悪くて嫌になってこない?
_ Zend_Aclのresourceの解決
Zend_Aclで、roleの方はスキーマ定義の段階でだいたい決まることが多いだろうし、それを解決するタイミングもユーザー識別の段階でほぼ確定だろうけど、resourceの方はどうやって解決するのが妥当だろう?
ドキュメントにある例では、resourceを指定せず(すべてのresourceに対して)roleごとに操作権限を設定するようになっているけど、よく使われるのは(すべてのresourceに対する)操作権限を管理するパターンではなく、どのresourceにアクセスできるかを管理するパターンだろう。たとえば、管理ツールには管理者のみがアクセスできる、とか。
そう言う場合、やっぱりmodule=resourceと考えて、Zend_Auth_Plugin_Abstract::preDispatch()あたりで、認証結果から確定したrole+リクエストから抜き出したmodule=resourceとして、$acl->isAllowed()するのが常道かな。module単位よりも細かい単位でアクセス制御したい場合は、function getResourceName($request)みたいなメソッドを用意して、requestから対応するresourceを解決するようにするとか。
ただ、SNSみたいにresourceとroleの関係を動的に解決しなければならないことが多いアプリケーションの場合、Zend_Aclをどう使うのがいいのかはまだ未解決。プラグインとかの共通層では対応が難しそうだから、roleとresourceの関係は抽象化した形で登録しておいて、アクションコントローラの末端でgetResource()とgetRole()を実装して突き合わせるしかないかな。それとも末端でローカルなZend_Aclオブジェクトを生成(=resourceもroleもローカルな定義を作り直す)した方がいいんだろうか。
ちなみに、ようやくZend_Session、Zend_Auth、Zend_Aclを実践的に使ってみているけど、思ったよりもだいぶ使いやすくなっていた。Zend_AuthとZend_Auth_Adapterの関係がちょっとわかりにくかったけど。
_ しょうもないバグを見つけた
Zend_Logでmaskとorしているのを見つけたとき以来のしょーもないバグ。まだこんなのが残っているのか。
ちなみになんでこれを見つけたのかというと、ErrorControllerの中で、
$this->getResponse->setHttpResponseCode(403);
をした場合に、なぜかviewRendererでデフォルトのテンプレートがレンダリングされないという症状にはまったから。「Zend_Controller_Response_Abstract::setHttpResponseCode(403)でisRedirect()がtrueにセットされる」→「Zend_Controller_Action_Helper_ViewRenderer::postDispatch()で、render()するかどうかの条件に!$this->getResponse()->isRedirect()を見ている」という原因ね。


