【CakePHP3】Cellを使ってヘッダーにお知らせを表示してみる。
がっつり体調を崩して寝込んでました。fukasawaです。こんにちは。
年末ということで気が緩んでたのでしょうか。皆様も体調には十分お気をつけください。アップしきれなかった記事を2015年にスッと差し込んで、未練なく新年を迎えたいと思います。
さて、今回はCakePHP3のCellを使って「ヘッダーに簡単なお知らせを表示する」というのをやってみたいと思います。
CellというのはCakePHP3から追加された機能で、簡易的なコントローラ+エレメントのセットです。
CakePHP2以前にもエレメントがありましたが、エレメントには紐づくコントローラの処理というものがありませんでした。なので、例えば「ヘッダーに簡単なお知らせを表示する」という機能を実装するため、レイアウトにお知らせ表示用のエレメントを埋め込んだ場合、そのエレメントからrequestAction()でコントローラを呼び出しデータを取得してきて表示する等の実装をしていました。
これはこれでちゃんと動くのですが、ビューからコントローラを呼び出すというのがなんだかムズムズする感じです。
Cellにはエレメントと異なり簡易的なコントローラが付いているので、このあたりの実装をもう少しスマートに行うことができます。
※CakePHP 3.1.0 で検証
1. 簡単な使い方
「DBからお知らせを1件ランダムに取得し、ヘッダーにお知らせを表示する」という機能を作っていきます。
お知らせを入れておくAnnouncesテーブルをDBに用意しました。以下のような状態になっています。
1. クラスを作る
まず、クラスを作ります。簡易的なコントローラとして動く部分です。\src\View\Cell\配下にxxxxxCell.phpという名前で作ります。今回はお知らせを表示する機能なので、AnnounceCell.phpという名前で作成しました。
\src\View\Cell\AnnounceCell.php
<?php
namespace App\View\Cell;
use Cake\View\Cell;
class AnnouncesCell extends Cell
{
public function display_header()
{
$this->loadModel('Announces');
$announce = $this->Announces->find()->order(['rand()'])->first();
$this->set('announce', $announce);
}
}
※ AnnounceCellはCellクラスを継承します。
Annoucesテーブルからお知らせをランダムで1件取得し、テンプレートに渡すdisplay_header()というアクションを定義しました。CellはModelAwareTraitやViewVarsTraitを使用しているため、loadModel()やset()といったメソッドが使えます。
2. テンプレートを作る
テンプレート(エレメントにあたる部分)を作っていきます。\src\Template\Cell\配下に作成します。
- AnnouncesCellという名前でクラスを作ったので、Announcesというディレクトリを作成
- display_header()というアクションを作ったので、Announcesディレクトリの下にdisplay_header.ctpというファイルを作成
\src\Template\Cell\Announces\display_header.ctp
<div class="announce">
<?php
if(!empty($announce)){
echo $this->Html->link(
$announce['title'],
$announce['url'],
array('escape' => false)
);
}
?>
Html::link()を使用して、アクションから渡された$announceをリンクとして表示しています。
3. レイアウトの修正
作成したCellを表示するためにレイアウトを修正します。今回はCakePHPのデフォルトレイアウト(default.ctp)を使用しているので、<body>タグの真下に下記の記述を追加しました。
\src\Template\Layout\default.ctp
<body>
<?= $this->cell("Announces::display_header"); ?>
…
AnnouncesCellのdisplay_header()アクションを呼んでいます。
4. 動作確認
default.ctpをレイアウトとして使用しているページを表示してみます。
お知らせが表示されました。リロードするたびに異なるお知らせがランダムで表示されます。
ちょっと見た目を整える為にCSSを適当に修正してみました。
.announce {
background-color: #363636;
color: #cccccc;
font-size: 14px;
text-align:right;
height: 30px;
line-height: 18px;
padding: 4px 10px;
}
こんな感じになりました。とりあえず完成です。
2. アクションに引数を渡す。
Cellを呼び出す際、アクションに値を渡すことができます。
cell("Announces::display_header",[$mode, $this->request->action]); ?>
第二引数に指定した値が、アクションの引数として渡されます。
\src\View\Cell\AnnounceCell.php
public function display_header($mode = 'first', $action = 'add')
{
...
}
3. 任意のテンプレートを使用する
display_action()というアクションが呼ばれた場合、デフォルトではdispaly_action.ctpというテンプレートが使われますが、これを別のテンプレートに変更することができます。Cellを呼び出す際、
<?= $this->cell("Announces::display_header")->render('display_popup'); ?>
もしくは
<?php
$cell = $this->cell("Announces::display_header");
$cell->template = 'display_popup';
echo $cell;
?>
と書くと、display_popup.ctpがテンプレートとして使われます。