こんばんは、Webプログラマの篠田です。
気がつけば蝉の鳴き声も聞かなくなり、朝の気温もだいぶ下がってきて夏の終わりを感じます。
短い冬までの過ごしやすい季節を堪能したいと思います!
今回はテンプレートエンジンの真骨頂(?)的な部分である「extends(エクステンド:継承)」「block(ブロック)」という考え方についてご紹介していきたいと思います。
この記事の目次
こんなとき、どうしたら良いか?
下記のようなTwigのテンプレートファイルがアルとします。
1 2 3 4 5 6 7 8 9 10 11 12 |
<!DOCTYPE html> <html> <header> <meta charset="UTF-8"> <meta description=“テストディスクリプション"> <meta keywords=“test,test2,test3"> <title>テスト</title> </header> <body> <h1>Hello {{ message }}!</h1> </body> </html> |
それほど特殊な内容は書かれていませんね。
問題は、このテンプレートの「description」と「keyword」そして「title」がページごとに変わるとしたらどうしたらいいでしょうか?
「変数にしてしまう」という素敵な回答がひらめいた方は、是非続きを読んでくださいね。
では、変数で作るとどうなるか見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 |
<!DOCTYPE html> <html> <header> <meta charset="UTF-8"> <meta description=“{{ description }}"> <meta keywords=“{{ keywords }}"> <title>{{ title }}</title> </header> <body> <h1>Hello {{ message }}!</h1> </body> </html> |
なんだか、いい感じのように思いますね。。。
では、このテンプレートを読み込むプログラム側も見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php require_once './vendor/autoload.php'; $loader = new Twig_Loader_Filesystem('./views/'); $twig = new Twig_Environment($loader); echo $twig->render('index.twig', array( 'description' => 'テストディスクリプション’, 'keywords' => ’test,test2,test3’, 'title' => 'テスト’, 'message' => 'twig World’ )); |
もちろん、これでも意図したとおりに動きます。ですが、同じようなテキストをプログラム側で用意して、大量の連想配列として送るというのは面倒ではないでしょうか?
それに、テキストの変更をテンプレートを触れる人に対応してもらいたいと思っても、プログラムファイルに記述されていると、ハードルが高く感じて、結局プログラマが変更するなんていう手間が掛かりそうな予感がします。
では、どうすればプログラマに取って手離れが良いテンプレートになるかを考えてみましょう。
●手離れのいいテンプレート像
(1)システムで管理しなくてもよい部分はプログラマは極力触らない
(2)デザイナーさんに、それなりに気持よく変更してもらいたい
(3)変更ファイルは1ファイル程度で汎用性を維持したい
ようは、ロジック(プログラム側)とビュー(デザイン側)を、ある程度綺麗にして、metaとかのよく変更が発生しそうな部分はビューにまとめておきたいというイメージです。
では、具体的にどのように管理すると比較的、素敵な運用ができるかを見ていきたいと思います
ベーステンプレートを作ろう
ベーステンプレートというのは私が勝手に言っているのですが、ようは全ページで共通して利用しているHTML部分を書きだしたテンプレートファイルという意味合いです。
先ほどの簡単なテンプレートをもとにベーステンプレートを作ってみましょう。
ファイル名は「base.twig」としておきます。
1 2 3 4 5 6 7 8 9 10 11 |
<!DOCTYPE html><html> <header> <meta charset="UTF-8"> <meta description=“"> <meta keywords=“"> <title></title> </header> <body> </body> </html> |
ただのHTMLになってしまいましたが、よく考えてみると全ページで使う部分といわれるとこの内容になりますよね。
もちろん、デザインによってはもう少しbodyの中身が共通として使える場合もありますが、今回はこれをベースとして考えてみたいと思います。
次にbodyの中身を「index.twig」として書き出しておきます。
ここまでで、2つのTwigファイルができあがりました。
プログラム側でテンプレートを読み込む
では、テンプレートを読み込むプログラム側も用意してみてみましょう。
1 2 3 4 5 6 7 8 9 10 11 |
<html> <header> <meta charset="UTF-8"> <meta description=“"> <meta keywords=“"> <title></title> </header> <body> </body> </html> |
これでOKです。
「あれ?base.twigは?」という声が聞こえたり、聞こえなかったり。。。
このままでは、「base.twig」は誰も読んでいないのでmetaを含まない結果が表示されてしまいます。
ですが、決してプログラム側で「base.twig」を呼んではいけません。
それでは、メインコンテンツである「index.twig」が表示されなくなってしまいます
メインテンプレートからベーステンプレートを読み込む
メインテンプレートである「index.twig」とベーステンプレートである「base.twig」をどうやって1つのファイルとして扱うのか。。。
前回お話しした「include」を使うとどうなるでしょうか?
下記のように「index.twig」を変更してみました。
1 2 |
{% include 'base.twig' %} <h1>Hello {{ message }}!</h1> |
実行してみると、残念がらhtmlの後にh1タグが表示されるという事態になると思います。
では、どうすればよいかというと、ここで使うのが冒頭で出てきました「extends(エクステンド:継承)」と「block」です。
「継承」とか言われると難しい印象をもたれる方もいると思いますが、今回はざっくりとしたイメージとして「include」の上位版とでも思ってもらうと分かりやすいかもしれません。
※逆に分かりにくくなったらすみませんm(_ _)m
では、「extends」と「block」を使うとどうなるかというのを見てみましょう。
1 2 3 4 |
{% extends 'base.twig' %} {% block content %} <h1>Hello {{ message }}!</h1> {% endblock %} |
こんな感じになります。「base.twig」が「index.twig」と同階層にあるという状況で作っています
これを実行すると今度は「真っ白」になると思います。
ただ、ソースを開けて見てみると「base.twig」が読み込まれていることがわかると思います。
では、「block」で囲まれた部分はどこへ行ってしまったのか。。。
それを解決するために「base.twig」を少し書き換えてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 |
<!DOCTYPE html> <html> <header> <meta charset="UTF-8"> <meta description=“"> <meta keywords=“"> <title></title> </header> <body> {% block content %}{% endblock %} </body> </html> |
これでOKです。
この「{% block content %}{% endblock %}」というのが
「index.twig」で用意した「{% block content %}{% endblock %}」と対になる部分になります。
これで、再度実行してみましょう。
文字が表示されたのではないでしょうか?
ではどのように動いているのかを簡単に解説していきましょう。
「extends」と「block」の動き
ざっくりとですが、「extends」と「block」は下記のような流れで動いているイメージです。
(1)「index.twig」が「base.twig」を継承する
(2)「base.twig」が読み込まれる
(3)「base.twig」内にある「{% block ●● %}{% endblock %}」に対になる内容が「index.twig」にあるかを探す
(4)対になる「{% block ●● %}{% endblock %}」があれば「base.twig」にある「{% block ●● %}{% endblock %}」が「index.twig」の内容に置き換わる
(5)表示完了
「●●」の部分は任意なので好きな名前をつけることができます。
先ほどの「content」も私が勝手につけています。
これをもとにmetaをテンプレートごとに書き換える仕様でテンプレートを用意してみます。
まずは「base.twig」を下記のように記述します
1 2 3 4 5 6 7 8 9 10 11 12 |
<!DOCTYPE html> <html> <header> <meta charset="UTF-8"> <meta description=“{% block description %} {% endblock %}"> <meta keywords=“{% block keywords %}{% endblock %}"> <title>{% block title %}{% endblock %}</title> </header> <body> {% block content %}{% endblock %} </body> </html> |
次に「index.twig」を下記のように記述します。
1 2 3 4 5 6 7 |
{% extends 'base.twig' %} {% block description %}テストディスクリプション{% endblock %} {% block keywords %}test,test2,test3{% endblock %} {% block title %}テスト{% endblock %} {% block content %} <h1>Hello {{ message }}!</h1> {% endblock %} |
これを実行すると綺麗に「base.twig」と「index.twig」が1つになりました。
まとめ
Twigの「extends」と「block」をうまく使うことで共通化を行い、拡張性を上げることができます。
プログラマは、できるだけデザイナーさんに使ってもらえるテンプレートファイルを作っていきたいですね。
では、またー!