【CakePHP3】Cellを使ってヘッダーにお知らせを表示してみる。

【CakePHP3】Cellを使ってヘッダーにお知らせを表示してみる。

がっつり体調を崩して寝込んでました。fukasawaです。こんにちは。
年末ということで気が緩んでたのでしょうか。皆様も体調には十分お気をつけください。アップしきれなかった記事を2015年にスッと差し込んで、未練なく新年を迎えたいと思います。

さて、今回はCakePHP3のCellを使って「ヘッダーに簡単なお知らせを表示する」というのをやってみたいと思います。

CellというのはCakePHP3から追加された機能で、簡易的なコントローラ+エレメントのセットです。
CakePHP2以前にもエレメントがありましたが、エレメントには紐づくコントローラの処理というものがありませんでした。なので、例えば「ヘッダーに簡単なお知らせを表示する」という機能を実装するため、レイアウトにお知らせ表示用のエレメントを埋め込んだ場合、そのエレメントからrequestAction()でコントローラを呼び出しデータを取得してきて表示する等の実装をしていました。
これはこれでちゃんと動くのですが、ビューからコントローラを呼び出すというのがなんだかムズムズする感じです。

Cellにはエレメントと異なり簡易的なコントローラが付いているので、このあたりの実装をもう少しスマートに行うことができます。

※CakePHP 3.1.0 で検証

1. 簡単な使い方

「DBからお知らせを1件ランダムに取得し、ヘッダーにお知らせを表示する」という機能を作っていきます。

20151231_fukasawa_01.png

お知らせを入れておくAnnouncesテーブルをDBに用意しました。以下のような状態になっています。

20151231_fukasawa_02.png

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をレイアウトとして使用しているページを表示してみます。
お知らせが表示されました。リロードするたびに異なるお知らせがランダムで表示されます。

20151231_fukasawa_03.png

ちょっと見た目を整える為にCSSを適当に修正してみました。

.announce {
  background-color: #363636;
  color: #cccccc;
  font-size: 14px;
  text-align:right;
  height: 30px;
  line-height: 18px;
  padding: 4px 10px;
}

こんな感じになりました。とりあえず完成です。

20151231_fukasawa_04.png

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がテンプレートとして使われます。

  • このエントリーをはてなブックマークに追加

この記事を読んだ人にオススメ