[Zend Framework][Twig]Zend FrameworkのViewをTwigで拡張する

by admin on 12月 28th, 2009

以前の記事で試しに使ってみたTwigですが、これをZend Frameworkの標準のViewにしたいな!ということでやってみました。

とあるブログの記事を参考にして組み上げているので、若干パクリが入っています。

ごめんなさい。

注意事項

この記事を書いた時点で利用しているそれぞれのバージョンは以下のとおりです。

Zend Framework 1.10.0 alpha 1
Twig 0.9.5 DEV

今後のバージョンアップによって動作に何かしら違いが出ると思いますので、ご注意ください。

下準備

まずは、Zend FrameworkでTwigを利用するための下準備を行います。

プロジェクトを作る

まずは、適当にプロジェクトを作ります。

1
$ zf create project twig_test

プロジェクトファイルができたら「library」フォルダに「My」フォルダを作っておきます。

次に以前の記事と同様にTwigをダウンロードします。

ダウンロードしたら、展開し、展開されたフォルダの「lib」フォルダ以下にある「Twig」フォルダを「twig_test/library」にコピペします。

Bootstrap.phpにNamespaceを追加するやつを書く

「twig_test」の直下にある「Bootstrap.php」を編集していきます。

以下のコードを記述します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected function _initNamespace() {
$autoloader = new Zend_Application_Module_Autolaoder(array(
"basePath" => realpath(APPLICATION_PATH. "/../library"),
"namespace" => ""
));
$autoloader->addResourceType("my", "My", "My");
return $autoloader;
}
[/php]

<span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px;">リソースのタイプを追加し、「library」以下に配置した時に、自動で読み込まれるようにします。(若干使い方おかしいかもですが...</span>

次はTwigのTwig_Autoloader::autoload()をZend_Loader_Autoloaderに追加します。

[CC lang="php"]
protected function _initAutoloaderNamespace()
{
$autoloader = $this->bootstrap("FrontController")->getApplication()->getAutolaoder();
$autoloader->pushAutoloader(array("Twig_Autolaoder", "autoload"));
}

で、次にZend_Viewの代わりにMy_Twig_Vewを登録してあげます。

1
2
3
4
5
6
7
protected function _initTwigView()
{
$options = $this->getOption("twig");
$view = new My_Twig_View(APPLICATION_PATH. "/views/scripts", $options);
$renderer = Zend_Controller_Action_HelperBroker::getStaticHelper("viewRenderer");
$renderer->setView($view)->setViewSuffix("html");
}

ここまでがBootstrap.phpの設定です。

次に「application/config/application.ini」を編集していきます。

1
2
3
4
5
6
twig.debug       = true
twig.trim_blocks = false
twig.charset     = "utf-8"
twig.base_template_class = "Twig_Template"
twig.cache       = APPLICATION_PATH "/views/caches"
twig.auto_reload = true

この設定は、Twig_Environmentクラスで設定するキャッシュなどの設定です。

上から順に「デバッグ」、「空白除去の可否(?)」、「チャーセット」、「テンプレートのベースクラス名」、「キャッシュパス」、「キャッシュ更新を自動で行うか」です。

チャーセットはネタですごめんなさい。

この設定項目はTwig公式のTwig for Developpersページを見てください。

My_View_Twigを作る

次に、実際に表示させるためのクラス「My_View_Twig」を作ります。

流れ的には、「Zend_View_Interface」をインプリして、実装内容を実装していくだけです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
<?php
class My_View_Twig implements Zend_View_Interface
{
/**
* Twig PHP Flexible template engine Core.
*
* @access private
* @var    Twig
*/

private $_twig;
/**
* Twig Template loader
*
* @access private
* @var    Twig_Loader Object
*/

private $_loader;
/**
* View valiables.
*
* @access private
* @var    Array
*/

private $_viewVars = array();
/**
* Constructor
*
* @access public
* @param  String     Twig laoder name
*supported types is Array, Filesystem, String
* @param  String
* @param  Array
*/

public function __construct($templatePath, $twigParams = array())
{
if(!is_readable($templatePath)) {
throw new My_View_Exception(&quot;can't readable '$templatePath'&quot;);
}
// cache path
if(!empty($twigParams[&quot;cache&quot;])) {
if(!is_dir($twigParams[&quot;cache&quot;])) {
throw new My_View_Exception($twigParams[&quot;cache&quot;]. &quot; is not directory.&quot;);
}
if(!is_readable($twigParams[&quot;cache&quot;])) {

throw new My_View_Exception(
$twigParams[&quot;cache&quot;]. &quot; is can'
t writeable. check this directory reable.&quot;
);
}

if(!is_writeable($twigParams[&quot;cache&quot;])) {
throw new My_View_Exception(
$twigParams[&quot;cache&quot;]. &quot; is can't writeable. check this directory writeable.&quot;
);
}
}
try {
// loadable Twig Loader class.
$this-&gt;_loader = new Twig_Loader_Filesystem($templatePath);
$this-&gt;_twig = new Twig_Environment($this-&gt;_loader, $twigParams);
}
catch(Exception $e) {
throw new My_View_Exception($e-&gt;getMessage());
}
}
/**
* Return the template engine object, if any
*
* If using a third-party template engine, such as Smarty, patTemplate,
* phplib, etc, return the template engine object. Useful for calling
* methods on these objects, such as for setting filters, modifiers, etc.
*
* @return mixed
*/
public function getEngine()
{
return $this-&gt;_twig;
}
/**
* Set the path to find the view script used by render()
*
* @param string|array The directory (-ies) to set as the path. Note that
* the concrete view implentation may not necessarily support multiple
* directories.
* @return void
*/
public function setScriptPath($path)
{
$this-&gt;_loader-&gt;setPaths($path);
return $this;
}
/**
* Retrieve all view script paths
*
* @return array
*/
public function getScriptPaths()
{
return $this-&gt;_loader-&gt;getPaths();
}
/**
* Set a base path to all view resources
*
* @param  string $path
* @param  string $classPrefix
* @return void
*/
public function setBasePath($path, $classPrefix = '
Zend_View')
{
}
/**
* Add an additional path to view resources
*
* @param  string $path
* @param  string $classPrefix
* @return void
*/
public function addBasePath($path, $classPrefix = '
Zend_View')
{
}
/**
* Assign a variable to the view
*
* @param string $key The variable name.
* @param mixed $val The variable value.
* @return void
*/
public function __set($key, $val)
{
$this-&gt;_viewVars[$key] = $val;
return;
}
/**
* Get valiable to the key
*
* @access public
* @param  String $key The valiable name
* @return Void
*/
public function __get($key)
{
if(isset($this-&gt;_viewVars[$key])) {
return $this-&gt;_viewVars[$key];
}
return null;
}
/**
* Allows testing with empty() and isset() to work
*
* @param string $key
* @return boolean
*/
public function __isset($key)
{
return ($this-&gt;_viewVars[$key] !== null);
}
/**
* Allows unset() on object properties to work
*
* @param string $key
* @return void
*/
public function __unset($key)
{
if(isset($this-&gt;viewVars[$key])) {
unset($ths-&gt;_viewVArs[$key]);
}
return true;
}
/**
* Assign variables to the view script via differing strategies.
*
* Suggested implementation is to allow setting a specific key to the
* specified value, OR passing an array of key =&gt; value pairs to set en
* masse.
*
* @see __set()
* @param string|array $spec The assignment strategy to use (key or array of key
* =&gt; value pairs)
* @param mixed $value (Optional) If assigning a named variable, use this
* as the value.
* @return void
*/
public function assign($spec, $value = null)
{
if(is_array($spec)) {
foreach($spec as $key =&gt; $val) {
$this-&gt;_viewVars[$key] = $val;
}
}
$this-&gt;_viewVars[$spec] = $value;
return $this;
}
/**
* get view vars
*
* @access public
* @return Array
*/
public function getVars()
{
return $this-&gt;_viewVars;
}
/**
* Clear all assigned variables
*
* Clears all variables assigned to Zend_View either via {@link assign()} or
* property overloading ({@link __get()}/{@link __set()}).
*
* @return void
*/
public function clearVars()
{
$this-&gt;_viewVars = array();
return $this;
}
/**
* Processes a view script and returns the output.
*
* @param string $name The script script name to process.
* @return string The script output.
*/
public function render($name)
{
$template = $this-&gt;_twig-&gt;loadTemplate($name);
$template-&gt;display($this-&gt;getVars());
}
}

実装内容は全部「Zend_View_Interface」からコピペです。

こんな感じでかけたら後は、リロードすればOKなはずです。

Exceptionに関しては、My/View内にExceptionを拡張市てもOKですし、単なるExceptionでもOKだと思います。

で、試しに「IndexController/indexAction」に以下のような記述をしてみます。

1
2
3
4
5
$this->view->hoge = array(
"param1" =&gt; 1,
"param2" =&gt; 2,
"param3" =&gt; 3
);

後はビューファイルから変数を参照すれば表示されるハズです。

「views/scripts/index/index.html」に簡単に書いてみます。

1
2
3
4
<h1>Twig Test</h1>
<p>{{ hoge.param1 }}</p>
<p>{{ hoge.param2 }}</p>
<p>{{ hoge.param3 }}</p>

正常に記述とかパスとかいろいろあっていればPタグにそれぞれ1〜3の数字が記述されていると思います。

Twigって素敵

私も最近知ったのですが、このテンプレートエンジンはいいなぁと思いました。

名前もなんか好きw(トゥイッグ?トゥワイ?)

おまけ

Twigには{% debug hoge%}と書いてあげると、PHPのvar_export()が実行された内容が吐き出されます。

が、var_dump()のがいい!!という場合は、Twig_Node_Debug.phpをコピーしてTwig_Node_Dump.phpにリネーム、Twig_TokenParser_Debug.phpをTwig_TokenParser_Dump.phpにリネームして上げます。

これらのコピーしたファイルをエディタで開き、「debug」と記述されている処を「dump」に変更すればvar_dump()の出力になるはずです。

わざわざ拡張子泣くてもいいかなぁとは思いましたけどついやってしまいました。

参考URL一覧

09/12/29 追記

すみません。

APPLICATION_PATH/configsのapplication.iniに以下の内容を追記しないと動かないです…。

単に書き忘れてしまっていました…。

1
autoloaderNamespaces.twig = "Twig"

これはAutoloaderにTwigという名前の名前空間を追加しています。

これは他の外部ライブラリなどでも同様に記述できます。

例にDoctinreを挙げてみると

1
autoloaderNamespaces.doctrine = "Doctrine"

と、こんな感じになります。

これを追記しないと、「$autoloader->pushAutolaoder(array(“Twig_Autoloader”, “autoload”))」の部分でコールバックとして正しくないよ!というエラーが吐き出されます。

From → Twig, Zend Framework

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS