2010年9月15日水曜日

zend frameworkでルーターの設定をiniファイルで行う

どうも、俺@仕事中です。

今日はZendFrameworkでルーティングの設定(Zend_Controller_Router_Route)を直接コードに書かずにiniファイルで行う設定方法の備忘録です。

1)通常のルーティング
$ vim configs/router.ini
-------------------------------
routes.default.type = "Zend_Controller_Router_Route"
routes.default.route = ":controller/:action/*"
routes.default.defaults.module = "module_name" ; モジュール名
routes.default.defaults.controller = "index" ; デフォルトコントローラ名
routes.default.defaults.action = "index" ; デフォルトアクション名

$ vim public/index.php
-------------------------------
$router = Zend_Controller_Front::getInstance()->getRouter();
$config = new Zend_Config_Ini(APPLICATION_PATH . "/configs.router.ini");
$router->addConfig($config, "routes");
これであれば
http://koexuka.blogspot.com/foo/bar/
というURLでアクセスのあった場合、「module_name」モジュールの「foo」コントローラの「bar」アクションが呼ばれます。


2)ホスト名によるルーティング
$ vim configs/router.ini
--------------------------------
; デフォルト
routes.default.type = "Zend_Controller_Router_Route"
routes.default.route = ":controller/:action/*"
routes.default.defaults.module = "module_name"
routes.default.defaults.controller = "index"
routes.default.defaults.action = "index"

; 携帯用
routes.mobile.type = "Zend_Controller_Router_Route_Hostname"
routes.mobile.route = "m.koexuka.blogspot.com"; ホスト名はm
routes.mobile.defaults.module = "mobile"; mobileモジュールへ
routes.mobile.defaults.controller = "index"
routes.mobile.defaults.action = "index"
routes.mobile.chains.path.type = "Zend_Controller_Router_Route"
routes.mobile.chains.path.route = ":controller/:action/*"
routes.mobile.chains.path.defaults.controller = "index"
routes.mobile.chains.path.defaults.action = "index"

$ vim public/index.php
-------------------------------
$router = Zend_Controller_Front::getInstance()->getRouter();
$config = new Zend_Config_Ini(APPLICATION_PATH . "/configs.router.ini");
$router->addConfig($config, "routes");
これで
http://m.koexuka.blogspot.com/foo/bar
というURLでアクセスのあった場合、「mobile」モジュールの「foo」コントローラの「bar」アクションが呼ばれます。


設定ファイルを利用した方がよりスマートだと思います。

以上でぇぇえぇす。

2010年9月10日金曜日

ZendFrameworkでモジュール別Bootstrapを用意すると全て実行されてしまう

どうも、俺@始業です。
忘れないうちにメモメモ。

Zend Frameworkはモジュール別Bootstrap.phpを用意して利用すると、どのモジュールですべてのBootstrapクラスにある_initXX()メソッドが実行されてしまいます。

モジュールの設定
$ vim application.ini
--------------------------------
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.modules[] =

fooモジュールとbarモジュールがあった場合は
$ vim modules/foo/Bootstrap.php
--------------------------------
class Foo_Bootstrap extends Zend_Application_Module_Bootstrap {
protected function _initFoo() {
// 何らかの前処理
}
}

$ vim modules/bar/Bootstrap.php
---------------------------------
class Bar_Bootstrap extends Zend_Application_Module_Bootstrap {
protected function _initBar() {
// 何らかの処理
}
}
↑↑どこのモジュールからでも両方のメソッドが実行されてしまう。
なんかモジュール毎にBootstrap置く意味がないですね。というかこれだったら
application/Bootstra.php内にすべて処理を済ませてしまえば良いのです。

なのでモジュールごとにBootstrapを実行させる方法をめも。
※ココを参考にしました。Phly, boy, phly
要は各Bootstrap内で、プラグインを登録しそこで処理を実行させちゃいなよ、YOU。ということです。
$ vim modules/foo/Bootstrap.php
--------------------------------
class Foo_Bootstrap extends Zend_Application_Module_Bootstrap {
protected function _initFoo() {
$this->bootstrap("FrontController");
$front = $this->getResource("FrontController");
$front->registerPlugin(new My_Plugin_Foo()); // ここでプラグイン登録
}
}

次にプラグインを作成します。
$ vim My/Plugin/Foo.php
--------------------------------
class My_Plugin_Foo extends Zend_Controller_Plugin_Abstract {
/**
* @Override
*/

public function dispatchLoopStartup(Zend_Controller_Requset_Abstract $req) {
if ($req->getModuleName() != "foo") { // ちょっとアナログな感じ、、
return;
}

// ここに処理
}
}
これでOKです。
barモジュールも同様にすれば良いです。
また処理ごとにMy_Plugin_Foo_XXとか My_Plugin_Foo_YYとかクラスを分けた方が分かりやすいと思います。


ただ、注意するのはモジュール内のBootstrapでプラグインを登録する方法だと、
実際に処理が実行されるタイミングがルータが動作した後だったりするので、完全な意味での「前処理」が出来ない場合もあるので注意しましょう。


では、次回はもう1つの方法をメモしときまぁぁす。

2010年9月8日水曜日

zend frameworkでZend_Filterを設定かつZend_Layoutを使うと文字化け

どうも、俺@仕事中です。

タイトルの通り、zend framework(v1.10.8)でZend_Filterを使ってviewにフィルタをかけて(実際は絵文字変換)、さらにZend_Layoutを利用すると文字化けが発生してしまいました。

Zend_Filterはこんな感じ(省略してます)
<?php
class My_View_Filter implements Zend_Filter_Interface {
public function filter($output) {
return mb_convert_encoding($output, "SJIS-win", "UTF-8");
}
}

で、コントローラのinit()メソッドで
public function init() {
$this->view->setFilterPath("My/View", "My_View_")->addFilter("Filter");
}
としてフィルタをセットしています。
レイアウトはapplication.iniの設定で
resources.layout.layout = "layout"
resources.layout.layoutPath = APPLICATION_PATH "/views/layouts"
としてレイアウトを有効にしています。

これだと、どうやらそれぞれのviewスクリプトに対しフィルタがかかり、さらに全てのviewスクリプトを含んだlayout.phtmlでさらにフィルタがかかるという2重フィルタ処理で文字化けが起こっているようです。

※このブログでも言及されていました。骨折り損のくたびれ儲け::ZendFrameworkで携帯 文字化け対応

上記のブログと同じ現象なのでこれで解決かな?と思ったのですが、なぜかうまくいきません。
1)独自のZend_Layout_Controller_Plugin_Layoutを拡張したクラスを作成
<?php
class My_Layout_Controller_Plugin_Layout extends Zend_Layout_Controller_Plugin_layout {
plubic function postDispatch(Zend_Controller_Request_Abstract $request) {
parent::postDispatch($request);
$filter = new My_View_Filter();
$this->getResponse()->setBody($filter->filter($this->getResponse()->getBody()));
}
}

2)application.iniに追記
resources.layout.pluginClass = "My_Layout_Controller_Plugin_Layout"


やり方が間違っているのか、、でも上のpostDispatch()メソッドで親クラスのを一度呼び出してるから文字化けするんじゃ??とも思うのですが、、
正しい方法があれば教えてください><

で、解決方法ですが、↑で作ったクラスなどはそのままにしておいてZend_View_Abstractクラスのrender()メソッドをちょこっと変更すればできます。
public function render($name) {
-- 中略 --
// return $this->_filter(ob_get_clean());
return ob_get_clean();
}


Zend_View_Abstractクラスを拡張しても良いかもしれませんね。

以上でぇぇす。

-- 2010.09.08 追記 --
Zend_Viewクラスを拡張したバージョンを作りました。
まず拡張クラスを作ります。
<?php
class My_View extends Zend_View {
private $_file = null;
// 一応
private $_useViewStream = false;
private $_useViewStreamWrapper = false;

public function render($name) {
$this->_file = $this->_script($name);
unset($name);

ob_start();
$this->_run($this->_file);
return ob_get_clean(); // ここは親クラスと違う
}
}

次はこの拡張Viewクラスを使うようindex.phpか、またはBootstrapに(※この例ではBootstrapを利用)
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
protected function _initView() {
$view = new My_View(array()); // コンストラクタの引数はViewに渡すオプション配列、またはZend_Config
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper("ViewRenderer");
$viewRenderer->setView($view);
}
}

以上でーす。

2010年9月7日火曜日

漢のzshでプロンプトに色をつける

どうも、俺@もうちょいで定時です。

最近書くネタがないので、.zshrcの設定でプロンプトに色をつける方法をメモっときます。
$ vim ~/.zshrc
---------------------------------------
autoload colors
colors

PROMPT="%{${fg[yellow]}%}[%n]# %{${reset_color}%}" # 左側
PROMPT2="%{${fg[yellow]}%}}->: %{${reset_color}%}"# 2行以上のプロンプト表示
SPROMPT="%{${fg[yellow]}%}correct:%R -> %r [n y a e]? %{${reset_color}%}"# 入力を間違えたときの表示
RPROMPT="%{${fg[cyan]}%}[%~]%{${reset_color}%}"# 右側


これで色がつきますよー。