最近CakePHP2とCakePHP3を並行で使っていて、ページタイトルのセット方法が違うことに違和感を感じていました。
CakePHP2では、コントローラのアクションメソッドで$title_for_layout
をsetして、ビューで$title_for_layout
を表示していましたが、CakePHP3ではビューで$this->assign('title', '表示したいタイトル')
とセットして$this->fetch('title')
で呼び出します。*1
ビューでページタイトルを設定するのでも支障は無いのですが、コントローラで設定できたほうが使い勝手がいいんですよね。
少しググった限りだとコントローラでsetした$titleを無理やりレイアウトの<title><?= $title ?>
する荒業みたいなものしかヒットしなかったので*2 、無理のない方法を書いておきます。
コントローラでセットした$titleをAppViewでassignする
CakePHP3ではビューに親クラスのAppView
が用意されているので、initialize()`メソッドを利用して、コントローラで$titleがsetされていたらassignするとスマートかと思います。
class AppView extends View { public function initialize() { if (!empty($this->viewVars['title'])) { $this->assign('title', $this->viewVars['title']); } } }
これだと$title
がセットされていない場合には、デフォルトのコントローラ名がtitleにassingされます。
私はアプリケーション(サイト)名をbootstrap.php
で定数やConfigure
に定義する*3 のですが、ページタイトルをサイト名と組み合わせるのにも応用できます。
public function initialize() { $title = ''; if (!empty($this->viewVars['title'])) { // コントローラでセットされたtitleを代入してセパレータを追加 $title .= $this->viewVars['title'] . ' | '; } $title .= SITE_NAME; // SITE_NAMEという定数にサイト名が定義されているとして $this->assign('title', $title); }
コントローラでページタイトルを設定したい理由
一番の理由は長年使い続けたCakePHP1,2の習慣だと思います。
でも、コントローラでセットしたほうが自然だよなぁと思う理由もいくつかあります。
ページタイトルはビジネスロジックが決めるから
ビジネスロジックがそもそもない一般のWEBサイトだと異なりますが、WEBシステムの場合ページタイトルはビジネスロジックによって決まります。そのページが何をするページなのかがタイトルになるので、○○を追加、〇〇レポート、〇〇インポートのような感じになります。
ビジネスロジックを表すページタイトルですから、物理的に別ファイルとなるビューで定義するよりは、ビジネスロジックに近接して書いておきたいというのが理由の一つです。
変数を利用したタイトル
※CakePHP3の習熟度が低いのでCakePHP2的に書きます。
たとえばBlog
モデルの1件分の詳細ページ。このページタイトルはBlog.title
になるのが自然です。
Blogモデルからデータを取得するのはコントローラのアクションなので、取得直後にtitleをセットできるコントローラがいいのではという考えです。
ビューでassingする場合だと、コントローラでBlogの取得処理を書いてからビューでassignを書くまでに少しタイムラグができますよね。
私の脳のスペックだとこの僅かなタイムラグによって「えっと、変数名は・・・フィールド名は・・・」と、思い出すのに少しコストがかかるのですぐに書きたいんですよね(笑)
あとがき
CakePHP2から3への変更はとても大きいので、このような仕様変更に対する戸惑いや違和感はまだまだ出てきそうです。
これはLaravelやSymfonyを触った時も同じように感じたのですが、自分の既存の知識と比較して経験豊富な過去のやり方のほうが魅力的に思えてしまうからなんでしょうね。
今回の記事のように無理やり過去のやり方を踏襲するのではなく、新しいやり方をしっかり経験した上でどちらが良いのかという判断をしないと「モダンなベストプラクティス」から取り残されてしまいます。
今はまだCakePHP3の経験が浅いので前のやり方のほうが良かったと思うことがありますが、CakePHP3の作法に則って身につけていきたいと思います。
- この記事を書くのにマニュアルを見て知りましたがCakePHP2.5から
$title_for_layout
は非推奨でCakePHP3の方法が推奨されていたんですね。 [↩] - この方だと$titleがsetされていないとエラーが出てしまうので、空の場合の条件分岐が必要になる。それにデフォルトだとtitleがassignされない時にコントローラ名からtitleを作成してくれるが、それも活かせない。 [↩]
- 案件のスタート時点で正式なサイト名が決まらないことが多いので、サイトタイトルやシステムからの送信元メールアドレスなどシステム内で使いまわす値をbootstrapにまとめて定義しています。こうすると後で変更するのもラクですし、納品後にクライアントで変更することも可能になるので便利です。 [↩]