CakePHPのデフォルトレイアウト「default.ctp」を読み解く | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

CakePHPに限らず多くのフレームワークは、レイアウトを制御し所定のフォーマットを各画面に適用する機能を持っています。

ちょっとしたデザイン変更をしたい場合やユーザーの設定によりテーマを切り替えさせたいといった場合、レイアウトの機能をうまく使いこなせればかなり効率化でき便利に使えます。



デフォルトのレイアウトファイルを読み解く


CakePHPのレイアウト機能でどのようなことができるのかは、デフォルトで用意されているレイアウトファイルを見てみると大体のことがわかってきます(ここでは、バージョン2.3.1を使っています)。


$cakeDescription = __d('cake_dev', 'CakePHP: the rapid development php framework');
?>
<!DOCTYPE html>
<html>
<head>
    <?php echo $this->Html->charset(); ?>
    <title>
        <?php echo $cakeDescription ?>:
        <?php echo $title_for_layout; ?>
    </title>
    <?php
        echo $this->Html->meta('icon');

        echo $this->Html->css('cake.generic');

        echo $this->fetch('meta');
        echo $this->fetch('css');
        echo $this->fetch('script');
    ?>
</head>
<body>
    <div id="container">
        <div id="header">
            <h1><?php echo $this->Html->link($cakeDescription, 'http://cakephp.org'); ?></h1>
        </div>
        <div id="content">

            <?php echo $this->Session->flash(); ?>

            <?php echo $this->fetch('content'); ?>
        </div>
        <div id="footer">
            <?php echo $this->Html->link(
                    $this->Html->image('cake.power.gif', array('alt' => $cakeDescription, 'border' => '0')),
                    'http://www.cakephp.org/',
                    array('target' => '_blank', 'escape' => false)
                );
            ?>
        </div>
    </div>
    <?php echo $this->element('sql_dump'); ?>
</body>
</html>


CakePHPでアプリを作り始める際にはレイアウトは上記のような構造となっており、これは主にデバッグ用の機能がちりばめられています。

肝心のコンテンツ(/path/to/cakephp/app/View/AppName/TemplateName.ctp)を出力するのは、


<?php echo $this->fetch('content'); ?>


という1行だけでよいので、各Viewファイルで<html>から</html>までを書いているなら、上記の1行をdefault.ctpとして保存すれば余計なデバッグ情報を出さずにコンテンツのみを表示できます。
余談にはなりますが、バージョン2.3以前では$content_for_layoutという変数に上記の結果が含まれており、2.3以降でもこの変数は利用可能ですが、正しい書き方としては構文が上記のように変更されています。


このdefault.ctpの中で幾つか便利な機能が提供されています。


<?php echo $this->Html->charset(); ?>

上記は、HTML内のMETAタグの文字コードを定義してくれ、展開されると


<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />


という風に出力されます。
これの便利なところとしては、CakePHPの設定ファイル(core.php)とリンクしており


Configure::write('App.encoding', 'UTF-8');

の設定を拾ってMETAタグを生成してくれます。

他にも


echo $this->Html->css('cake.generic');


という書き方で、CSSを自動的に読込んでくれます。

このCSSは、「/path/to/cakephp/app/webroot/css/」ディレクトリ内にあるものを読込みます。

(拡張子の.cssは不要です)

LINKタグを書くよりは若干楽でしょうか。



ビューブロックを使ってレイアウトを動的に変える


レイアウトファイルは、抽象化したテンプレートファイルであるため、動的に出力するHTMLを変えていきたいというような要件がでてきます。

もちろん、コントローラー側でどうにかする方法もありますが、ビューブロックという機能を使えばより単純に後付でテンプレートの内容を変えていくということが可能です。


echo $this->fetch('meta');
echo $this->fetch('css');
echo $this->fetch('script');


デフォルトテンプレートの中では、上記のようなロジックが書かれている箇所がありますが、この箇所にViewファイル側から動的に結果を埋め込んでいくというようなことが可能です。

(デフォルトテンプレートだけでは、この結果は何も出力しませんが)


ビューブロックを使うには、下記のようにViewファイル側でそれぞれのブロックに出力する処理を書いていきます。

一番最初に書かれているmetaブロックに出力するには、


<?php $this->assign('meta', 'fugafuga'); ?>

または、


<?php
$this->start('meta');
echo "hogehoge";
$this->end();
?>


のような書き方ができます。

前者の書き方はmetaというブロックに文字列を割り当て、後者の書き方ではmetaというブロックの開始(start)を宣言し、終了(end)までの出力結果を割り当ててくれます。


また、デフォルトテンプレートに記載のmetaというブロックは、HTMLで言うところのMETAタグやLINKタグなどが出力されることを想定しているものだったりもしますので、下記のようにHTMLヘルパーを使ってmetaブロックにHTMLを出力することも可能です。


<?php $this->Html->meta('icon', 'favicon.ico', array("inline" => false)); ?>

上記の結果により、metaブロックに下記のHTMLが出力されます。


<link href="favicon.ico" type="image/x-icon" rel="icon" />

metaブロックへどこで出力の制御を行っているんだという話ですが、第3引数の配列キー「inline」をfalseで渡すとmetaブロックへ出力してくれます。

他にも、


$this->Html->meta('description', 'A great page', array('inline' => false));


という処理で、METAタグのdescriptionのHTMLをmetaブロックへ出力してくれたりします。

これは、CakePHP標準として実装されているHTMLヘルパーですので、cssやscriptの場合どうするのかや引数の詳細については、「/path/to/cakephp/lib/Cake/View/Helper/HtmlHelper.php」を参照してみてください。

または、CakePHPのマニュアル も参考になるかと思います。


レイアウトファイルは、テンプレートファイルのさらに元となるファイルですので、その共通部分をうまく抽出して定義してあげればデザインの変更や切り替え機能などが簡単に実装できるかもしれません。