forked from jelix/jelix-manual-en
-
Notifications
You must be signed in to change notification settings - Fork 0
/
zones.gtw
247 lines (159 loc) · 9.18 KB
/
zones.gtw
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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
~~LANG:FR@frman:zones~~
===== Zone's principles =====
Zones in Jelix represent small parts of the final response. They are intended to manage and generate the content of a part of the screen, the web page. A web page is then primarily made of zones.
What is interesting in using zones is to :
* be able to reuse a zone in different pages : a zone is in theory independent from the context : it calls business classes by itself and has its own template.
* have a generation of content that accept parameters.
* be able to generate pages faster, activating the zone's cache : only the zones whose parameters have changed (the main zone in general) are regenerated (or those whose cache hase been deleted).
* make the code of controllers lighter.
===== Using zones =====
==== Creation ====
A zone is declared with a class extending @@C@jZone@@. Its name must begin with "Zone".
<code php>
class ZoneTest extends jZone {
}
</code>
It must be placed in a @@F@name_of_zone.zone.php@@ file, in the @@F@zones/@@ directory of the module. In our example : it is the @@F@zones/test.zone.php@@ file.
A @@C@jZone@@ object instantiates its own template by default.
=== Using it without template ===
If you don't want to use a template for your zone, you have to overload the @@M@_createContent@@ method, which must return the content of the zone in the form of string. You mustn't use an echo or print !
<code php>
class testZone extends jZone {
protected function _createContent(){
return "<p>This is the content of a zone</p>";
}
}
</code>
=== Using it with a template ===
Most of the time, you will use a template. You have to indicate in the @@P@$_tlpname@@ property the template that you will use (using a selector), and overload the @@M@_prepareTpl()@@ method. This method is in charge of the initialization of the @@C@jTpl@@ object automatically instantiated by jZone and placed in the @@P@_tpl@@ property.
<code php>
class testZone extends jZone {
protected $_tplname='template_test';
protected function _prepareTpl(){
$this->_tpl->assign('foo','bar');
}
}
</code>
And the template (placed in @@F@templates/template_test.tpl@@):
<code xml>
<p>This is a template. And foo = {$foo}.</p>
</code>
==== Calling it ====
There are several ways to retrieve the content of a zone according to what we want to do.
If you simply want to retrieve its content (in a controller), you do :
<code php>
$content = jZone::get('test'); // or 'TheModule~test'...
</code>
However, you will often have to affect the content of the zone to a main template variable, when the response has a main template (which is the case of html responses, through its @@P@$body@@ property which is a jTpl object). In the controller, we will thus be able to use the @@M@assignZone@@ method of jTpl:
<code php>
$rep = $this->getResponse('html');
$rep->title = 'test page';
$rep->bodyTpl = 'testapp~main';
$rep->body->assignZone('MAIN', 'test');
</code>
* @@L@test@@ correspondant to the file @@[email protected]@@
* @@L@MAIN@@ correspondant to the template variable @@{$MAIN}@@
Another solution is to have a direct call to a zone in a template :
<code html>
<div id="menu"> {zone 'TheModule~test'}</div>
</code>
==== Calling it with parameters ====
It is possible pass parameters to a zone. Parameters should be in an associative array.
<code php>
$content = jZone::get('test', array('foo'=>'bar'));
</code>
With the @@M@assignZone@@ method of jTpl:
<code php>
$rep = $this->getResponse('html');
$rep->title = 'test page';
$rep->bodyTpl = 'testapp~main';
$rep->body->assignZone('MAIN', 'test', array('foo'=>'bar'));
</code>
To retrieve the variable in the zone, we use the @@M@param()@@ method :
<code php>
class testZone extends jZone {
protected $_tplname='template_test';
protected function _prepareTpl(){
$foo = $this->param('foo');
$foo = strtoupper($foo);
$this->_tpl->assign('foo', $foo);
}
}
</code>
In this example we pass the 'foo' variable with 'bar' value as parameter of the zone. We have retrieved the 'foo' variable in the zone to process it (here: to make it upper case) and we affected 'foo' to the template of the zone.
Don't forget that Jelix affects automatically the variables passed as parameters of the zone to the template of the zone if it exists. You then can avoid to write :
<code php>
protected function _prepareTpl(){
$this->_tpl->assign('foo', $this->param('foo');
}
</code>
If you use the zone plugin template, you pass the parameters to the zone this way :
<code html>
<div id="menu"> {zone 'TheModule~test', array('foo'=>'bar')} </div>
</code>
==== Using the cache ====
It is possible to put the generated content in a cache. And you can have a cache for each parameter value of the zone.
=== Enabling the cache ===
By default, a zone does not cache the generated content, so you should activate it in your class, via the property ''_useCache'':
<code php>
Class testZone extends jZone {
Protected $_useCache = true;
}
</code>
If the zone is called without parameters, there will be a single cache file. If you have several parameters, then there will be a cache file for each given value in parameters. For example, if you have an 'article_id' parameter, there will have some cache file for each value of article_id.
**Carefull**: a cache is a file in the temp directory of the application. If you have thousands of articles, it can generate as many files into your temporary directory. You should avoid to enable the cache if for example you have a limited number of files in your web hosting.
Use the cache wisely. For example, a moderately popular application (the same article read only about once a day), it is not necessary to activate the cache. You be the judge ...
=== Refreshing the cache ===
It is necessary to regenerate the cache when the information is obsolete. This regeneration can be done automatically regularly (all //n// seconds), or be forced manually.
You use one or the other methods as appropriate. The second method is less greedy in resource since the cache is regenerated when you do it. The disadvantage is that you should explicitly clear the cache in your business code. The first method avoids this job, but consumes more resources, and the content of the zone is not up to date during a laps of time. But it could not be vital if cached informations are not important.
== Automatic refresh ==
For an automatic refresh, you have just to indicate the time in @@P@$_cacheTimeout@@, in seconds:
<code php>
Class testZone extends jZone {
Protected $_useCache = true;
Protected $_cacheTimeout = 60;
}
</code>
Here, the cache will be regenerated every 60 seconds. If you put 0, there won't be automatic refresh.
== Forced refresh ==
The "manual" removal of cache is done via static methods @@M@clear()@@ and @@M@clearAll()@@..
For example, in the business class which manage your article, during the update of the article (in a database, for example) or when you delete it, you are going to call @@C@jZone@@ to delete the corresponding cache, so that it will be regenerated in the next display. Of course you should indicate the parameters values which identify the cache. In our example, therefore, ''id_article''.
<code php>
jZone::clear ( 'mymodule~product', array ( 'id_article' => 546));
</code>
If you want to delete all the caches at the same time, you can call @@M@clearAll()@@:
<code php>
jZone::clearAll('mymodule~product');
</code>
And if you want to delete all caches of all zone:
<code php>
jZone::clearAll ();
</code>
=== Prevent temporarily caching ===
It should be noted that the methods @@M@_createContent()@@ and @@M@_prepareTpl()@@ (that you can override), are called only when the cache must be regenerated. It may be that for some reason or another (depending on the value of a parameter for example), you don't want sometimes to use the cache of the zone.
To do it, in @@M@_createContent()@@ or @@M@_prepareTpl()@@, you just have to set @@P@$_cancelCache@@ property to @@true@@:
<code php>
protected function _prepareTpl {
/ / ....
$this->_cancelCache = true;
//...
}
</code>
=== Disable cache during development ===
To disable all zone cache, and thus be able to build your zone contents and see directly the results, you can set a config parameter, in [zones] section :
<code ini>
[zones]
disableCache = on
</code>
==== Automatics parameters ====
The display of a zone may depend explicitly given parameters, but also on "external" parameters implicitly. One example is a zone which displays the version of an article based on the language set in the app. You can of course indicate the code language at each call of the zone, but it is not practical. It might not have to indicate the parameters, and recover them in @@M@_createContent()@@ or @@M@_prepareTpl()@@, but then it is not possible for this implicit parameters to be criterions for the cache system.
The solution is to override the constructor, and initialize this parameter:
<code php>
class articleZone extends jZone {
protected $_useCache = true;
public function __construct ($params = array ()) {
$params['lang'] = jApp::config()->locale;
parent:: __construct ($params);
}
}
</code>