Quick links: Content - sections - sub sections
EN FR

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 jZone. Its name must begin with "Zone".


class ZoneTest extends jZone {

}

It must be placed in a name_of_zone.zone.php file, in the zone directory of the module. In our example : it is the zones/test.zone.php file.

A 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 _createContent method, which must return the content of the zone in the form of string. You mustn't use an echo or print !


<?php
class testZone extends jZone {

   protected function _createContent(){
      return "<p>This is the content of a zone</p>";
   }
}
?>

Using it with a template

Most of the time, you will use a template. You have to indicate in the $_tlpname property the template that you will use (using a selector), and overload the _prepareTpl() method. This method is in charge of the initialization of the jTpl object automatically instantiated by jZone and placed in the _tpl property.


<?php
class testZone extends jZone {

   protected $_tplname='template_test';

   protected function _prepareTpl(){
       $this->_tpl->assign('foo','bar');
   }
}
?>

And the template (placed in templates/template_test.tpl):



<p>This is a template. And foo = {$foo}.</p>

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 :


   $content = jZone::processZone('test'); // or 'TheModule~test'...

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 body property which is a jTpl object). In the controller, we will thus be able to use the assignZone method of jTpl :


    $rep = $this->getResponse('html');
    $rep->title = 'test page';
    $rep->bodyTpl = 'testapp~main';
    $rep->body->assignZone('MAIN', 'test');

Another solution is to have a direct call to a zone in a template :


  <div id="menu"> {zone 'TheModule~test'}</div>

Calling it with parameters

It is possible pass parameters to a zone. Here is what we do :

Call from a controller :


    $rep = $this->getResponse('html');
    $rep->title = 'test page';
    $rep->bodyTpl = 'testapp~main';
    $rep->body->assignZone('MAIN', 'test', array('foo'=>'bar'));

And to retrieve the variable in the zone, we use the getParam method() :


<?php
class testZone extends jZone {

   protected $_tplname='template_test';

   protected function _prepareTpl(){
       $foo = $this->getParam('foo');
       $foo = strtoupper($foo);
       $this->_tpl->assign('foo', $foo);
   }
}
?>

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 :


   protected function _prepareTpl(){
       $this->_tpl->assign('foo', $this->getParam('foo'););
   }

If you use the zone plugin template, you pass the parameters to the zone this way :


  <div id="menu"> {zone 'TheModule~test', array('foo'=>'bar')} </div>

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:


Class testZone extends jZone {
    Protected $_useCache = true;
}

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 _cacheTimeout, in seconds:


Class testZone extends jZone {

    Protected $_useCache = true;
 
    Protected $_cacheTimeout = 60;
}

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 clear and 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 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.


    jZone::clear ( 'mymodule~product', array ( 'id_article' => 546));

If you want to delete all the caches at the same time, you can call clearAll:


    jZone::clearAll('mymodule~product');

And if you want to delete all caches of all zone:


    jZone::clearAll ();

Prevent temporarily caching

It should be noted that the methods _createContent and _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 _createContent or _prepareTpl, you just have to set _cancelCache property to true:



    protected function _prepareTpl {
       / / ....
       $this->_cancelCache = true;
       //...
    }

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 _prepareTpl / _createContent, 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:


class articleZone extends jZone {

    protected $_useCache = true;

    public function __construct ($params = array ()) {
        $params ['lang'] = $ GLOBALS['gJConfig']->locale;
        parent:: __construct ($params);
    }
}