Raccourcis : Contenu - rubriques - sous rubriques
EN FR

Principes d'une zone

Les zones dans Jelix représentent des morceaux de la réponse finale. En d'autre termes, elles sont destinées à gérer et générer le contenu d'une portion de l'écran, de la page web. Une page web est donc composée essentiellement de zones.

L'intérêt d'utiliser les zones est de :

  • pouvoir réutiliser une zone dans des pages différentes : une zone est en théorie indépendante du contexte : elle fait elle-même appel aux classes métiers et possède son propre template.
  • avoir une génération de contenu paramétrable : les zones acceptent des paramètres.
  • pouvoir générer plus rapidement les pages, en activant la mise en cache des zones : seules les zones dont les paramètres changent (la zone principale en général) sont régénérées (ou celles dont on aura effacé le cache).
  • au passage, alléger le code des contrôleurs.

Utilisation des zones

Création

Une zone est déclarée via une classe héritant de jZone. Le nom de cette classe est le nom de la zone suivi du mot "Zone"


class testZone extends jZone {

}

Elle doit être stockée dans un fichier nom_de_la_zone.zone.php, dans le répertoire zones/ du module. Ici donc, il s'agit du fichier zones/test.zone.php.

Par défaut, un objet jZone instancie un moteur de template.

Utilisation sans template

Si vous ne voulez pas utiliser de template pour votre zone, vous devez surcharger la méthode _createContent, qui doit renvoyer le contenu de la zone sous forme de chaine. Vous ne devez pas faire d'echo ou de print !


class testZone extends jZone {

   protected function _createContent(){
      return "<p>Ceci est le contenu d'une zone</p>";
   }
}

Utilisation avec template

La plupart du temps, vous utiliserez toutefois un template. Vous devez indiquer dans la propriété $_tplname le template que vous utilisez (c'est un sélecteur), et surcharger la méthode _prepareTpl(). Cette méthode est, comme son nom l'indique, chargée d'initialiser l'objet jTpl instancié automatiquement par jZone et stocké dans la propriété _tpl.


class testZone extends jZone {

   protected $_tplname='template_test';

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

Et le template (stocké dans templates/template_test.tpl):


<p>Ceci est un template. Et foo vaut {$foo}.</p>

Création en utilisant jelix-scripts

Vous pouvez utiliser jelix-scripts pour créer votre zone accompagnée ou non d'un template.

Exécutez simplement la commande suivante :


php dev.php module:create-zone <MonModule> <MaZone> [<MonTemplate>]

où le paramètre <MonTemplate> est facultatif. Le nom du template est identique au nom de la zone dans ce cas.

Pour ne pas créer de template précisez simplement l'option --notpl.


php dev.php module:create-zone --notpl <MonModule> <MaZone>

Appeler une zone

Il y a plusieurs façons de récupérer le contenu d'une zone en fonction de ce que l'on veut faire.

Si on veut récupérer simplement son contenu (dans un contrôleur) on fait :


   $contenu = jZone::get('test'); // ou 'leModule~test'...

Cependant, il arrive très souvent qu'il s'agisse d'affecter le contenu de la zone à une variable du template principal, lorsque la réponse possède un template principal (ce qui est le cas des réponses HTML qui possèdent un objet jTpl dans sa propriété $body). Dans le contrôleur, on pourra donc utiliser la méthode assignZone de jTpl :


    $rep = $this->getResponse('html');
    $rep->title = 'page de test';
    $rep->bodyTpl = 'testapp~main';
    $rep->body->assignZone('MAIN', 'test');
  • test correspondant au nom du fichier test.zone.php
  • MAIN correspondant à la variable de template {$MAIN}

Autre solution, on peut avoir dans un template, un appel de zone direct :


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

Appel avec des paramètres

Il est possible de faire passer des paramètres à une zone. Il faut les passer par un tableau associatif.


   $contenu = jZone::get('test', array('foo'=>'bar'));

Avec la méthode assignZone de jTpl :


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

Pour récupérer la variable dans la zone, on utilise la méthode param() :


class testZone extends jZone {

   protected $_tplname='template_test';

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

Dans cet exemple on a fait passer la variable 'foo' avec pour valeur 'bar' en paramètre de la zone. On a récupéré la variable 'foo' dans la zone pour effectuer un traitement dessus (ici, mise en majuscule) et on a affecté 'foo' au template de la zone.

À noter que Jelix affecte automatiquement les variables passées en paramètres de la zone au template de zone s'il existe. Vous pouvez vous passer d'écrire :


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

Si vous utilisez le plugin de template zone, le passage des paramètres à la zone s'effectue de cette manière :


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

Utilisation du cache

Il est possible de mettre le contenu généré dans un cache. Et il peut y avoir un cache pour chaque valeur des paramètres de la zone.

Activation du cache

Par défaut, une zone ne gère pas de cache : il faut donc l'activer dans votre classe, via la propriété $_useCache en la mettant à true :


class testZone extends jZone {

   protected $_useCache = true;
}

Le contenu de la zone sera ainsi mis dans un fichier de cache. Si la zone a des paramètres, un cache sera créé pour chaque valeur différente des paramètres. Ainsi, si vous avez un paramètre 'id_article', un cache sera créé à chaque fois que la zone sera appelée avec une valeur de id_article différente.

  • *ATTENTION** : un cache se matérialise par un fichier dans le répertoire temporaire de l'application. Si vous avez des milliers d'articles, cela peut engendrer autant de fichiers dans votre répertoire temporaire. Il faut donc éviter dans un cas comme celui-là, d'activer le cache si votre hébergeur vous limite en nombre de fichiers par exemple.

Utilisez donc le cache à bon escient. Par exemple, pour une application fréquentée moyennement (un même article lu seulement quelque fois par jour), il n'est pas forcément nécessaire d'activer le cache. À vous de juger...

Rafraîchissement du cache

Il est nécessaire de régénérer le cache quand les informations contenues sont obsolètes. Cette régénération peut se faire automatiquement régulièrement (toutes les n secondes), ou alors être forcée manuellement.

Vous utiliserez l'une ou l'autre des méthodes selon les cas. La deuxième méthode est moins gourmande en ressource puisque le cache se régénère uniquement en temps voulu. L'inconvénient c'est qu'il faut explicitement effacer le cache dans vos classes métier. La première méthode évite ce travail, mais consomme plus de ressources, et le contenu de la zone n'est pas à jour pendant le délai indiqué. À réserver donc pour afficher des informations non vitales, dont la "fraîcheur" n'a pas vraiment d'importance.

Automatique

Pour un rafraîchissement automatique, il suffit d'indiquer dans la propriété $_cacheTimeout le délai d'invalidité du cache, en secondes :


class testZone extends jZone {
 
   protected $_useCache = true;
 
   protected $_cacheTimeout = 60; 
}

Ici le cache sera régénéré toutes les 60 secondes. Si vous mettez 0, il n'y aura pas de rafraîchissement automatique.

Forcé

La suppression "manuelle" du cache se fait via les méthodes statiques clear() et clearAll().

Par exemple, dans la classe métier de votre article, au moment de modifier l'article (en base de données par exemple) ou de le supprimer, vous allez appeler jZone pour qu'il supprime le cache correspondant, afin qu'il soit régénéré au prochain affichage. Bien sûr, il faut indiquer les valeurs des paramètres qui identifient le cache. Dans notre exemple donc, id_article.


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

Si vous voulez effacer tous les caches d'une même zone, vous pouvez appeler clearAll() :


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

Et si vous voulez effacer tous les caches de toutes les zones :


   jZone::clearAll();

Empêcher dynamiquement la mise en cache

Il faut noter que les méthodes _createContent() et _prepareTpl() (que vous pouvez surcharger), ne sont appelées que lorsque le cache doit être régénéré.

Il se peut que pour une raison ou pour une autre (en fonction de la valeur d'un certain paramètre par exemple), vous ne vouliez pas que parfois le résultat de la zone soit mis en cache.

Il suffit alors, dans _createContent() ou _prepareTpl(), de mettre la propriété $_cancelCache à true.


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

Désactiver les caches pendant le développement

Parfois, il peut arriver que l'on veuille désactiver le cache des zones, pour voir le résultat de ces zones quand on les modifie. Pour cela, vous pouvez modifier un paramètre dans la configuration, au niveau de la section [zones]


[zones]
disableCache = on

Paramètres automatiques

L'affichage d'une zone peut dépendre de paramètres donnés explicitement, mais aussi de paramètres "externes" implicites. C'est le cas par exemple pour une zone qui affiche la version d'un article en fonction de la langue configurée dans l'application. On peut bien sûr passer à chaque appel de zone le code langue, mais ce n'est pas forcément pratique. On pourrait ne pas avoir à l'indiquer dans les paramètres, et le récupérer soi-même dans _createContent() ou _prepareTpl(), mais alors il n'est pas possible que cela devienne un critère discriminant pour le système de cache si vous l'utilisez.

La solution est de surcharger le constructeur, et d'initialiser ce paramètre :


class articleZone extends jZone {

   protected $_useCache = true;

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

}