menu
書いてる野郎
orebike@gmail.com
controllerはある特定のViewのためにデータのお膳立てをするための場所と思っていいい。
逆に言うとある特定のViewのためにmodelにグチャグチャ何かを書いちゃいかんということ
CakePHP/命名規則に従ってファイルとクラス名を決めて、AppControllerクラスを継承して作る。そして
app/controllers
ディレクトリに配置する。
functionで定義しているのがコントローラ本体の実際のロジック、一般的なフレームワークではこのロジック部をアクションとか言いますな。 クラスはそれの取りまとめという感じか。
class HogeController extends AppController{ function index(){ //hogehogehoge } }
AppControllerを継承していればどう作ってもいいということはアプリごとの共通なものはAppControllerを継承したクラスにまとめて記述して、 それを個々のコントローラーのクラスが継承するという設計にするといいだろう。
コントローラーの呼び出しは CakePHPのアプリのルートから
コントローラー名(のキャメル化)/アクション名
になる。
http://aaaa.com/bbb/hoge/index
のようになるわけだ。
コントローラーが HogePiyoController のような名前の場合は
http://aaa.com/bbb/hogePiyo/index
のように頭だけ小文字に変化する。URLに大文字が交じるのはちょっとキモイのでコントローラー名はなるべく1単語でシンプルにしたいな。
この記述は
config/routes.php
にデフォルトで書かれている設定に従っているだけで、これを変えられないわけではない。
共通処理を書くだけの継承専用のオリジナルコントローラーを作ると思うがこのコントローラーもURLの対象に入ってしまうので当然ブラウザからしかるべきURLでアクセスすればたどりつける。
やってほしくないので共通コントローラーはabstract宣言をくっつけてオブジェクト化を禁止しておく。これでよし。
後方互換性のためにコントローラー名を明示的に指定することになっている。これは命名規則と同期していれば特に問題ないので思考停止していれておこう。
メンバ変数は name という名前になる
class HogeController extends AppController{ public $name = 'Hoge'; function index(){ //hogehogehoge } }
なのでAction中でコントローラー名を使いたいと思ったら
hoge = $this->name;
だ。
コントローラー内部で使われるモデルは予めCake側がnewしてくれるのでその参考情報としてモデル名の一覧を指定する。
メンバ変数は uses という名前になる。指定は配列で行う。
class HogeController extends AppController{ public $name = 'Hoge'; public $uses = array('Piyo', 'Fuga'); function index(){ //hogehogehoge } }
モデルを使わないコントローラーでは null を指定しておけばいい。
通常はアクション名の関係から辿ってテンプレートが自動決定される。これをauto renderと言う。 auto renderの設定がデフォルトでOnになっている。
class HogeController extends AppController{ public $name = 'Hoge'; public $uses = array('Piyo', 'Fuga'); public $autoRender = true; function index(){ //hogehogehoge } }
こいつを明示的にアクション名とは別のテンプレートを呼び出したかったりとか、そういう時に false を指定するとそれを止めることができる。
autoLayoutに値を設定するとレイアウトファイルを使うかどうかを切り替えられます
class HogeController extends AppController{ public $name = 'Hoge'; public $uses = array('Piyo', 'Fuga'); public $autoLayout = false; public $autoRender = true; function index(){ //hogehogehoge } }
設定値は単なるプロパティなので
$this->autoLayout = false;
のようにアクションメソッド中に書き換えてしまえばOK
コントローラーの本来のメソッド(indexとかshowとかeditとか)の前に呼ばれるメソッドがbeforeFilterメソッドでこいつをコントローラーのクラスに書いておくと本来の動きの前に処理を割りこませることができる。
つまり全部のActionに共通で使う前処理をここで書いておけばいいのだ。このbeforeFilterは引数が取れないようだ。
beforeFilterメソッドが親でももうすでに定義されていた場合、子で作ると親が呼び出されないので明示的に呼んでおく
function beforeFilter(){ parent::beforeFilter(); }
テンプレートの呼び出し前に動くのがbeforeRenderメソッド。共通の後処理ってことね。
function beforeRender(){ parent::beforeRender(); }
テンプレートが全部出力し終わった後にさらにコールされるメソッドがある
function afterFilter(){ echo "hoge"; }
ここでの出力は標準出力に出てしまうので。テンプレートの出力に対して後付できたりする。
注意しないといけないのはこのメソッドはアクションのメソッド中で
$this->redirect("hoge/piyo");
ってリダイレクトしたり
exit;
ブチッと切ってしまうと実行されないということ。
afterFilterの処理内容をredirectをトラップして行っておくといいかもしれない
テンプレートの出力をウマイことキャッチすることで最終的な出力を加工できるようになる。
画面の出力直前でob_start関数を呼び出して、出力のキャプチャ準備をする
function beforeRender(){ ob_start(); }
出力が全部終わった時点で、出力した内容をob_get_contentsで取得、その後に画面に出力されないようにob_end_cleanでクリアしてしまう。
その後に加工してechoすることで再びリターンとして出力する。
function afterFilter(){ $hoge = ob_get_contents(); ob_end_clean(); //ここらへんで出力に対する操作をして echo $hoge; }