routes.phpで設定した特定のルーティングに従ったURLでアクセスされた場合にモデルのdisplayField
を動的に変更する方法。例えばURLが「/hoge/users/」だったらdisplayField
を"hoge_name"
、「/fuga/users/」だったら"fuga_name"
にするなど。
誰が得するのかわからないですが、とりあえずメモっておく。
CakePHP1.2.7で確認。そろそろ1.3に移行したいところ。
要するに同じモデルでもアクセスされたURLによってdisplayFieldを切り替えたい場合、特に特定のモデルだけでなく全部一括で変えたい場合に使えるテクです。っていつ使うんだって思いますが、いつかそういうこともあります。
まずroutes.phpに次のように書いてあるとします。
Router::connect('/hoge/:controller/:action/*', array('hoge' => true)); // パターン1
Router::connect('/fuga/:controller/:action/*', array('fuga' => true)); // パターン2
こうすると「/hoge/任意のコントローラ/任意のアクション」も「/fuga/任意のコントローラ/任意のアクション」のいずれも動作的には同じになります。
ただし、コントローラ内で$this->params
の内容に違いが出ます。パターン1では$this->params["hoge"]
にtrue
が入り、パターン2では$this->params["fuga"]
にtrue
が入った状態になります。コントローラ内ではこれを利用して動作を変化させることができます。
しかしモデル内では$this->params
などというプロパティが存在しません。最初に思いつくのはコントローラのbeforeFilter
メソッド内で定数やらを定義してモデルのコンストラクタで読み取ったり図ろうとするでしょう。残念なことにモデルのコンストラクタの方が先に呼び出されるので、その方法は使えません。
そこで出てくるのが、Router::getParam()
です。第1引数に”hoge”や”fuga”を与えてやれば、コントローラの$this->params
を参照したときと同じものが得られます。ということでこれを利用して、app_model.phpのコンストラクタにガシっと処理を書いてしまいます。
class AppModel extends Model {
public function __construct($id = false, $table = null, $ds = null) {
if (Router::getParam('hoge')) {
$this->displayField = 'hoge_name';
} elseif (Router::getParam('fuga')) {
$this->displayField = 'fuga_name';
}
parent::__construct($id, $table, $ds);
}
}
これでモデル全部に対し、一括でdisplayField
の変更ができます。
一部のモデルを除きたい場合は独自のプロパティやdisplayField
のデフォルト値を設定するなどして、判定を追加すれば良いでしょう。
以上、誰得テクニックでした。
コメント