CakePHP3のテンプレート基本記法とレイアウトを用いたビュー開発を行う
- 公開日
- 更新日
- カテゴリ:CakePHP
- タグ:PHP,Beginner,MVC,CakePHP,Template,Layout,View

MVC の「V 」=「View 」にあたる画面表示部分の構築を、CakePHP3 では「テンプレート」と呼ばれる領域のファイルを作成する事で進めていきますが、いくつもあるビューテンプレートの中の共通部分を切り出し「レイアウト」という領域のファイルにまとめておく事ができます。
今回は、テンプレートの基本的な記法とレイアウトを用いてビュー開発を行います。
Contents
開発環境
今回の開発環境は以下の通りです。
- Linux CentOS 7
- Apache 2.4
- PHP 7.1
- CakePHP 3.5
CakePHP のバージョンは 3 系であれば同一手順で進めていけます。
CakePHP のルートディレクトリを「cakephp/」とします。
レイアウト
PHP フレームワークで言う「レイアウト」とは、ビュー(テンプレート)に使われる手法で、同一の HTML などをレイアウトとしてまとめておく事で、各コンテンツのビューはそのコンテンツの内容のみをコーディングすれば良くなり、効率化を図ることの出来る手法です。
例えば、HTML ヘッダやフッタをレイアウトとして作成しておくことで、各コンテンツのビューには、そのコンテンツのビューのみを記述すればよく、最終的にレイアウトとコンテンツのビューを合算した HTML としてブラウザに描画する事ができます。
ちなみに、CakePHP の初期ページなどにもレイアウトが導入されており、そのレイアウトファイルは
cakephp/src/Template/Layout/default.ctp
になります。
このように、cakephp/src/Template/Layout 配下に ctp ファイルを設置する事で、レイアウトファイルとして認識されます。
コントローラ作成
まずはコントローラから作成していきます。 cakephp のルートディレクトリへ移動し、以下の bake コマンドを叩いて Samples コントローラを生成します。
# CakePHP のルートディレクトリへ移動する
cd /path/to/cakephp
# bake コマンドでコントローラを生成する
bin/cake bake controller Samples
# 実行結果
[demo@localhost cakephp]# bin/cake bake controller Samples
Baking controller class for Samples...
Creating file /var/www/html/cakephp/src/Controller/SamplesController.php
Wrote `/var/www/html/cakephp/src/Controller/SamplesController.php`
Bake is detecting possible fixtures...
Baking test case for App\Controller\SamplesController ...
Creating file /var/www/html/cakephp/tests/TestCase/Controller/SamplesControllerTest.php
Wrote `/var/www/html/cakephp/tests/TestCase/Controller/SamplesControllerTest.php`
cakephp/src/Controller 配下に SamplesController.php
cakephp
├─ src
│ ├─ Controller
│ │ ├─ SamplesController.php
せっかく生成されたコントローラクラスですが、今回必要なものだけを残してあとは削除してしまい、それ(以下)を初期ソースとしてスタートします。
- cakephp/src/Controller/SamplesController.php
-
<?php namespace App\Controller; use App\Controller\AppController; class SamplesController extends AppController { public function index() { } }
レイアウト作成
それではレイアウトファイルを作成していきます。
cakephp/src/Template/Layout 配下に samples.ctp を作成します
cakephp
├─ src
│ ├─ Template
│ │ ├─ Layout
│ │ │ ├─ ajax.ctp
│ │ │ ├─ default.ctp
│ │ │ ├─ Email
│ │ │ ├─ error.ctp
│ │ │ ├─ rss
│ │ │ └─ samples.ctp
samples.ctp を以下のように記述します。
- cakephp/src/Template/Layout/samples.ctp
-
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, maximum-scale=1.0, minimum-scale=0.5,user-scalable=yes,initial-scale=1.0" /> <title><?= h($title) ?></title> <?php echo $this->Html->css('reset.css'); echo $this->Html->css('common.css'); echo $this->Html->css('samples/index.css'); ?> </head> <body> <div class="header"> <p class="logo"><?= env('APP_NAME') ?></p> </div> <h1><?= h($title) ?></h1> <?= $this->fetch('content') ?> <div class="footer"> <small>© 2018 <?= env('APP_NAME') ?></small> </div> </body> </html>
レイアウトには共通化出来そうな以下の要素をコーディングしました。
- DOCTYPE から head タグまでの、いわゆるメタ部分
- HTML ヘッダー
- ページタイトル(h1)
- HTML フッタ
そして、その間に記述されている
<?= $this->fetch('content') ?>
この部分が、コンテンツを表示する部分になります。
その他、各記述について少し解説します。
<?= h($title) ?>
コントローラから渡されるタイトル変数を表示します。
<?php
echo $this->Html->css('reset.css');
echo $this->Html->css('common.css');
echo $this->Html->css('samples/index.css');
?>
CSS ファイルを読み込んでいます。階層が異なっても、スラッシュ区切りで指定する事で読み込む事が出来ます。
ちなみに読み込むCSS を分けているのは、複数読み込む記述を行いたかっただけなので、そこは適宜最適化してください。
<?= env('APP_NAME') ?>
env ファイルから値を読み込む場合には以下のようにします。ここでは、アプリケーションの名前を読み込んでいます。
ビュー(テンプレート)作成
レイアウトが出来たので、コンテンツ部分のビューを作成していきます。
cakephp/src/Template 配下に Samples ディレクトリを作成し、index.ctp を作成します。
cakephp
├─ src
│ ├─ Template
│ │ ├─ Samples
│ │ │ └─ index.ctp
index.ctp を以下のようにコーディングします。
- cakephp/src/Template/samples/index.ctp
-
<ul class="php_list"> <?php foreach ($list as $li): ?> <li><?= $li ?></li> <?php endforeach; ?> </ul>
極めてシンプルですが、レイアウトを作成したので、ここでコーディングするのは本当にコンテンツ部分のみで良くなります。これが、レイアウトを導入するメリットの1つです。
CSS 作成
軽く見た目を整えるために、簡単に CSS を作成していきます。
リセット CSS
若干本編からは趣旨がずれますが、気持ち悪いのでリセット CSS を適用します。
- cakephp/webroot/css/reset.css
-
/* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 License: none (public domain) */ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } body { line-height: 1; } ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } table { border-collapse: collapse; border-spacing: 0; }
Eric Meyer's "Reset CSS" 2.0 のスタイルを採用させていただきました。
レイアウト用 CSS
レイアウトの samples.ctp に係るスタイルを記述します。
- cakephp/webroot/css/common.css
-
.header, .footer { padding: 20px; width: 100%; background-color: #2a88bd; } .logo { font-size: 20px; color: #FFFFFF; } .footer { text-align: center; } .footer small { font-size: 14px; color: #FFFFFF; } h1 { margin: 20px; font-size: 20px; }
コンテンツページ用 CSS
今回のコンテンツページに係るスタイルを記述します。
- cakephp/webroot/css/samples/index.css
-
.php_list { margin: 30px; } .php_list li { margin-bottom: 10px; }
コントローラ実装
それでは最後に、作成したレイアウトなどをコントローラに適用していきます。
- cakephp/src/Controller/SamplesController.php
-
<?php namespace App\Controller; use App\Controller\AppController; class SamplesController extends AppController { public function initialize() { // レイアウトの設定 $this->viewBuilder()->setLayout('samples'); } public function index() { // ビューに渡す変数 $title = 'PHPフレームワークのリスト'; $list = [ "Laravel", "CakePHP", "Symfony", "Zend Framework", "CodeIgniter", "Phalcon", "Slim", "Yii", "FuelPHP", "Silex", "Flight", "BEAR.Sunday", "Kohana", "Ethna", "Ice Framework" ]; // 変数をセットしビューに渡す $this->set(compact('title', 'list')); } }
initialize()(コンストラクタ)で、レイアウトの指定を行っています。先ほど作成した、samples.ctp を指定しています。
cakephp/src/Template/Layout 配下にレイアウトファイルを設置する事で、拡張子を除いたファイル名を記述すれば指定できるようになっています。
もちろん、Layout ディレクトリ配下に新たにディレクトリを作ってそこへ設置した場合でも「XXXX/samples 」のように記述すれば指定可能です。
変数は2つ設定しました。ビューに渡すタイトルと、コンテンツに渡す配列です。それらを、compact() メソッドにてビューへ set() しています。
動作確認
それではブラウザからアクセスして表示を確認してみます。
http://YOUR-DOMAIN/samples
ブラウザ右クリックから「ページのソースを表示」で、ソースコードも参照してみます
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, maximum-scale=1.0, minimum-scale=0.5,user-scalable=yes,initial-scale=1.0" />
<title>PHPフレームワークのリスト</title>
<link rel="stylesheet" href="/css/reset.css"/>
<link rel="stylesheet" href="/css/common.css"/>
<link rel="stylesheet" href="/css/samples/index.css"/>
</head>
<body>
<div class="header">
<p class="logo">test_app</p>
</div>
<h1>PHPフレームワークのリスト</h1>
<ul class="php_list">
<li>Laravel</li>
<li>CakePHP</li>
<li>Symfony</li>
<li>Zend Framework</li>
<li>CodeIgniter</li>
<li>Phalcon</li>
<li>Slim</li>
<li>Yii</li>
<li>FuelPHP</li>
<li>Silex</li>
<li>Flight</li>
<li>BEAR.Sunday</li>
<li>Kohana</li>
<li>Ethna</li>
<li>Ice Framework</li>
</ul>
<div class="footer">
<small>© 2018 test_app</small>
</div>
</body>
</html>
レイアウトとコンテンツのビューテンプレートが合算され、一連の HTML が問題なく表示されました。
まとめ
以上で作業は完了です。今回はデモンストレーションという事でコンテンツファイルは1つのみの作成でしたが、実際に開発を行う WEB アプリケーションはいくつもページがあるでしょう。そんな時にこうしてレイアウトで共通部分を定義しておけば、コンテンツのビューはそれだけをコーディングすれば良く、非常に効率的です。
また、共通部分に変更の必要が出た場合にも、レイアウトファイル1つだけを変更すれば良いので、更新漏れも防げますし、何より楽です。
このレイアウトという概念は CakePHP ならずとも、ほとんどの PHP フレームワークには導入されていますので、結構必須の機能です。覚えておけばどの PHP フレームワークを使ってもスムーズに導入できると思うので是非試してみてください。