[Zend Framework] Zend_Layout: テンプレートをつかってページを表示する
Zend_Layout をつかって、共通のヘッダーやメニューを表示するようなレイアウトを構成します。
参考サイト
Contents
レイアウト要素
一般的なページのレイアウトを想定して、下記のような構成要素を用意します。
- ヘッダー
- ナビゲーション
- コンテンツ
- アサイド
- フッター
テンプレートデザインには、Initializr を利用することにします。
Initializr – Start an HTML5 Boilerplate project in 15 seconds!
このようなページになります。
ダウンロードと下準備
responsive をオプションを変更せず、そのまま利用します。
ダウンロードしたファイルを、ひとまずそのまま公開ディレクトリに設置します。
zf enable layout
zf create project で作成したプロジェクトディレクトリ内で、下記コマンドを実行します。
% zf enable layout
下記のファイル・ディレクトリが、追記・作成されました。
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
<?php echo $this->layout()->content; ?>
ディレクトリ構成
Zend_Layout の利用にあたり、ディレクトリ構成を確認し、各ファイルを整えておきます。
ディレクトリの構成は、下記に従って用意します。
推奨されるプロジェクト・ディレクトリ構造 – Zend Framework MVC アプリケーションのために推奨されるプロジェクト構造 – Zend Framework
設定ファイル
- application/configs/application.ini
- application/Bootstrap.php
いわゆるリソースプラグインというものでしょうか。
最終的に、application.ini, Bootstrap.php にまとめます。
レイアウトテンプレート
- application/layouts/scripts/
配下に .phtml をおいていきます。
- layout.phtml (ディレクトリとともに zf で生成済)
- header.phtml
- footer.phtml
アサイドとナビゲーションは、ひとまず layout.phtml に含めておきます。
別途、ビューヘルパーを適用してみたいと思います。
なお、コンテンツは layout.phtml から呼ばれ、Contoroller 内の Action に対応した application/views/scripts/ 以下の .phtml が読み込まれることになります。
- application/views/scripts/index/index.phtml
HTML関連フォルダ
- application/public/css
- application/public/
imagesimg - application/public/js
- application/public/favicon.ico
ファイルは、Initializr をつかいます。
イメージフォルダ名のみ、推奨構造と異なることになります。
テンプレートファイルの作成
ひとまず準備が整ったので、テンプレートを作成します。
Initializr のファイル内の要素を各テンプレートに分割していきます。
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="css/normalize.min.css">
<link rel="stylesheet" href="css/main.css">
<script src="js/vendor/modernizr-2.6.2-respond-1.1.0.min.js"></script>
</head>
<body>
<!--[if lt IE 7]>
<p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p>
<![endif]-->
<div class="header-container">
<header class="wrapper clearfix">
<h1 class="title">h1.title</h1>
<nav>
<ul>
<li><a href="#">nav ul li a</a></li>
<li><a href="#">nav ul li a</a></li>
<li><a href="#">nav ul li a</a></li>
</ul>
</nav>
</header>
</div>
<div class="main-container">
<div class="main wrapper clearfix">
<article>
<header>
<h1>article header h1</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sodales urna non odio egestas tempor. Nunc vel vehicula ante. Etiam bibendum iaculis libero, eget molestie nisl pharetra in. In semper consequat est, eu porta velit mollis nec.</p>
</header>
<section>
<h2>article section h2</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sodales urna non odio egestas tempor. Nunc vel vehicula ante. Etiam bibendum iaculis libero, eget molestie nisl pharetra in. In semper consequat est, eu porta velit mollis nec. Curabitur posuere enim eget turpis feugiat tempor. Etiam ullamcorper lorem dapibus velit suscipit ultrices. Proin in est sed erat facilisis pharetra.</p>
</section>
<section>
<h2>article section h2</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sodales urna non odio egestas tempor. Nunc vel vehicula ante. Etiam bibendum iaculis libero, eget molestie nisl pharetra in. In semper consequat est, eu porta velit mollis nec. Curabitur posuere enim eget turpis feugiat tempor. Etiam ullamcorper lorem dapibus velit suscipit ultrices. Proin in est sed erat facilisis pharetra.</p>
</section>
<footer>
<h3>article footer h3</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sodales urna non odio egestas tempor. Nunc vel vehicula ante. Etiam bibendum iaculis libero, eget molestie nisl pharetra in. In semper consequat est, eu porta velit mollis nec. Curabitur posuere enim eget turpis feugiat tempor.</p>
</footer>
</article>
<aside>
<h3>aside</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sodales urna non odio egestas tempor. Nunc vel vehicula ante. Etiam bibendum iaculis libero, eget molestie nisl pharetra in. In semper consequat est, eu porta velit mollis nec. Curabitur posuere enim eget turpis feugiat tempor. Etiam ullamcorper lorem dapibus velit suscipit ultrices.</p>
</aside>
</div> <!-- #main -->
</div> <!-- #main-container -->
<div class="footer-container">
<footer class="wrapper">
<h3>footer</h3>
</footer>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.9.1.min.js"><\/script>')</script>
<script src="js/main.js"></script>
<script>
var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
</body>
</html>
header.phtml
<header class="wrapper clearfix">
から </header>
の内容。
<footer class="wrapper">
から </footer>
の内容。
コンテンツ
application/views/scripts/index/index.phtml
に、<article>
から </article>
の内容。
layout.phtml
application/public/index.html
の残り全ての内容。
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="css/normalize.min.css">
<link rel="stylesheet" href="css/main.css">
<script src="js/vendor/modernizr-2.6.2-respond-1.1.0.min.js"></script>
</head>
<body>
<!--[if lt IE 7]>
<p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p>
<![endif]-->
<div class="header-container">
<header class="wrapper clearfix">
<?= $this->render('header.phtml'); ?>
</header>
</div>
<div class="main-container">
<div class="main wrapper clearfix">
<article>
<?= $this->layout()->content; ?>
</article>
<aside>
<h3>aside</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sodales urna non odio egestas tempor. Nunc vel vehicula ante. Etiam bibendum iaculis libero, eget molestie nisl pharetra in. In semper consequat est, eu porta velit mollis nec. Curabitur posuere enim eget turpis feugiat tempor. Etiam ullamcorper lorem dapibus velit suscipit ultrices.</p>
</aside>
</div> <!-- #main -->
</div> <!-- #main-container -->
<div class="footer-container">
<footer class="wrapper">
<?= $this->render('footer.phtml'); ?>
</footer>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.9.1.min.js"><\/script>')</script>
<script src="js/main.js"></script>
<script>
var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
</body>
</html>
Zend_View の render メソッドで、ファイルを読み込みレンダリングしています。
<?= $this->render('header.phtml'); ?>
<?= $this->render('footer.phtml'); ?>
表示するコンテンツが自動で取得されレンダリングされており、これを書き出すだけでよいそうです。
<?= $this->layout()->content; ?>
スッキリと理解できていないんですが、Zend_Layoutでcontentはディフォルトで設定されており、その他は何を用いるかによってスクリプトが変わってくると言うことのようです。
参考サイト
表示
Initializr のファイルを削除しておきます。
% rm application/public/index.html
インデックスページを表示してみます。
sampleという文字を区別しやすいように入れておきました。
設定した各テンプレートがレイアウトされています。
ちなみに、他のコントローラではどうでしょうか?
存在しないURLを指定して、エラーコントローラを呼んでみます。
こちらも問題なくレイアウトが適用されていました。
結果的に、マニュアルにあるような startMvc() をしてないですし、Zend_Loader::loadClass(‘Zend_Layout’); もしてないんですが、表示がされました。
このあたりスッキリしないんですが、リソースプラグインをつかうとシンプルにできるんでしょうか?
以下の3つは、別の方法で実装してみます。
- ナビゲーション
- アサイド
- favicon.ico
補遺
部分的に、別レイアウトを適用する方法です。
アクション単位
$this->_helper->layout->setLayout('error');
コントローラ単位
あるコントローラだけ別のレイアウトを適用したい場合、init に設定を用意します。
この場合、application/layouts/scripts/error.phtml が適用されます。
public function init()
{
$options = array(
'layout' => 'error',
'layoutPath' => '../application/layouts/scripts',
'content' => 'content',
);
Zend_Layout::startMvc($options);
}
init() に下記を設定しても適用できました。
$this->_helper->layout->setLayout('error');
モジュール単位
application.ini に記述することで、設定できるようです。