1. Home
  2. PHP
  3. CakePHP
  4. CakePHP3のテンプレート基本記法とレイアウトを用いたビュー開発を行う

CakePHP3のテンプレート基本記法とレイアウトを用いたビュー開発を行う

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

MVC の「V 」=「View 」にあたる画面表示部分の構築を、CakePHP3 では「テンプレート」と呼ばれる領域のファイルを作成する事で進めていきますが、いくつもあるビューテンプレートの中の共通部分を切り出し「レイアウト」という領域のファイルにまとめておく事ができます。

今回は、テンプレートの基本的な記法とレイアウトを用いてビュー開発を行います。

Contents

  1. 開発環境
  2. レイアウト
  3. コントローラ作成
  4. レイアウト作成
  5. ビュー(テンプレート)作成
  6. CSS 作成
    1. リセット CSS
    2. レイアウト用 CSS
    3. コンテンツページ用 CSS
  7. コントローラ実装
  8. 動作確認

開発環境

今回の開発環境は以下の通りです。

  • 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>&copy; 2018 <?= env('APP_NAME') ?></small>
  </div>
</body>
</html>

レイアウトには共通化出来そうな以下の要素をコーディングしました。

  1. DOCTYPE から head タグまでの、いわゆるメタ部分
  2. HTML ヘッダー
  3. ページタイトル(h1)
  4. 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>&copy; 2018 test_app</small>
  </div>
</body>
</html>

レイアウトとコンテンツのビューテンプレートが合算され、一連の HTML が問題なく表示されました。

まとめ

以上で作業は完了です。今回はデモンストレーションという事でコンテンツファイルは1つのみの作成でしたが、実際に開発を行う WEB アプリケーションはいくつもページがあるでしょう。そんな時にこうしてレイアウトで共通部分を定義しておけば、コンテンツのビューはそれだけをコーディングすれば良く、非常に効率的です。

また、共通部分に変更の必要が出た場合にも、レイアウトファイル1つだけを変更すれば良いので、更新漏れも防げますし、何より楽です。

このレイアウトという概念は CakePHP ならずとも、ほとんどの PHP フレームワークには導入されていますので、結構必須の機能です。覚えておけばどの PHP フレームワークを使ってもスムーズに導入できると思うので是非試してみてください。

Author

rito

  • Backend Engineer
  • Tokyo, Japan
  • PHP 5 技術者認定上級試験 認定者
  • 統計検定 3 級