2012年9月21日金曜日

[CakePHP]layoutってcontrollerがrenderする前に処理してないか?

※このpostは前半部分間違った推測をしています。
 後で本当の原因がわかったので、最後に追記として書いています。


全てのControllerで共通してdefault.ctpというlayoutを使っている。
そこには、もしAuth認証でログイン済みであれば、ユーザ名と
プロフィール画像を表示するようにしている。

つまり、全ての画面で共通なロジックだからだ。

もちろんlogoutでレンダーされる画面にもそのlayoutが適用
されるんだけど、なぜかlogout画面でもユーザ名と
プロフィール画面が表示されてしまう。
赤で囲った部分はログイン状態でなければ表示されないはずの部分。



仮説だが、
「layout内の処理はControllerのrender処理の前に行われる。」
のではないか。

ちなみに、ログアウト画面表示後、TOP画面等を表示すると、
ちゃんとユーザ情報などは表示しないでくれていた。
なので、logout()の処理自体はどこかで動いていて、セッションから
ログイン情報を消してくれているはず。
そして、layout内の<?php echo $content_for_layout ?>を赤枠の部分より
上に配置してみたが、相変わらず表示された。

つまり、viewの部分がlayoutより上にあったとしても、処理としてはlayoutが先に行われて
いるということではないか。

仕方がないので、layout内でlogout後かどうかを判別する仕組みを入れた。
コントローラー側は以下の3行目にログアウト後であるフラグを入れた。
ちなみに、ここで$this->session->write()を使わず$this->set()を使ったのは、
前者だと、おそらく次以降の遷移後にもフラグが立ちっぱなしになってしまうので。
setは一度のrenderでしか有効でない。
 public function logout(){
  $this->Auth->logout();
  $this->set('logoutFlg',true);
 }


つづいてlayout側。(抜粋)
2行目の&&以降で、フラグに値が入っているかを確認している。
入っていなければ、logout後ではないのでユーザ情報を表示する。
 <?php
  if(!empty($auth['User']['id']) && empty($logoutFlg)){
   echo $this->element('loginInfo');
  }else{
   echo $this->element('loginLink');
  }
 ?>

※本当はせっかくtrueが入るからempty()とか使いたくなかったけど、
logout後以外は絶対に値がはいらないから$logoutFlgみたいにbooleanで
判別しようとすると、エラーになっちゃうんだよね。

こうすれば、ログアウト画面のユーザ情報は消えてくれた。
つまり、まとめると、

「layout内の処理はControllerのrender処理の前に行われる。
ただし、layout内でController側で設定された変数が必要な場合は、
Controllerの処理を待って処理をする。」

あくまで仮説です。
誰か、本当のところを知っている人教えて下さい。


【追記】
すみません。書いた直後に原因が発覚しました。
上で書いたことと全然違ってました。

自分はAppControllerのbeforeFilterで
    function beforeFilter(){
       $this->Auth->allow('*');
       $auth=$this->Auth->user();
       $this->set('auth',$auth);
    }
としていました。
$this->Auth->logout()はsessionにあるユーザ情報は消しますが、
set()された$authは消しません。(auth.phpのソースコード参照)
なので、logoutアクションでrenderされる画面にユーザ情報が表示されて
しまったということです。
そこで、Authのユーザ情報の取り出しはview側(layout)にて行うように
修正したところ、上記で追加したlogoutFlg無しでも正常にlogout画面が
ユーザ情報無しで表示されました。

そもそも、AppControllerにAuthのユーザ情報の取り出し処理を入れていた理由は、
全画面でやるので、全viewのファイルに書くのは嫌だなと思っていたからです。
でも、layoutに書いておけば一箇所でよいので、layoutに移しました。









0 件のコメント:

コメントを投稿