Astuce #7 - Jouons avec le Nom des Templates

This tip is also available in English.      

WARNING: Certaines parties de cette astuce ne fonctionnent qu'avec la dernière version de symfony 1.1 et seulement si vous avez mis à jour votre fichier .htaccess.

Par défaut, symfony devine le nom et le répertoire de la template à utiliser en se basant sur le nom de l'action exécutée.

Prenons comme exemple un module content qui contient une action static et qui se trouve dans l'application frontend:

<?php
 
class contentActions extends sfActions
{
  public function executeStatic()
  {
  }
}
 

En appelant l'action content/static, symfony charge le fichier staticSucces.php et le cherche dans le répertoire apps/frontend/modules/content/templates/.

symfony a ajouté Success en suffixe car le code précédent est équivalent à celui-ci:

<?php
 
class contentActions extends sfActions
{
  public function executeStatic()
  {
    return sfView::SUCCESS; // sfView::SUCCESS == 'Success'
  }
}
 

A priori, l'action content/static devant pouvoir gérer plusieurs fichiers statiques différents, nous devons trouver un moyen de passer un nom de page dans la requête pour s'en servir dans la détermination du nom de la template à utiliser. Ajoutons pour cela une règle de routing:

page:
  url:   /static/:page
  param: { module: content, action: static }
 

Voyons maintenant comment mettre à jour l'action afin de prendre en compte ce paramètre dans le nom de la template.

Changer le suffix

La première chose que l'on peut faire est de changer le suffixe par défaut Success en retournant explicitement le nom de la page :

<?php
 
class contentActions extends sfActions
{
  public function executePage($request)
  {
    return $request->getParameter('page');
  }
}
 

Si nous accédons maintenant à la page /static/about, symfony chargera la template staticabout.php.

Voici le répertoire templates/ qui contient deux pages différentes :

templates/
  staticabout.php
  staticcontact.php
 

Changer le nom de la template

Plutôt que de changer le suffixe, on peut également changer le nom de la template comme ceci:

<?php
 
class contentActions extends sfActions
{
  public function executePage($request)
  {
    $this->setTemplate($request->getParameter('page'));
  }
}
 

En accédant à la page /static/about, symfony va maintenant charger la template aboutSuccess.php.

Voici le contenu du répertoire templates/:

templates/
  aboutSuccess.php
  contactSuccess.php
 

Comme le module content peut contenir d'autres actions, il peut être intéressant de mettre toutes les templates de l'action static dans un sous-répertoire. Ceci peut être fait simplement en préfixant le nom de la template avec le nom du sous-répertoire :

<?php
 
class contentActions extends sfActions
{
  public function executePage($request)
  {
    $this->setTemplate('static/'.$request->getParameter('page'));
  }
}
 

Et symfony charge maintenant la template static/aboutSuccess.php.

Voici le contenu du répertoire templates/:

templates/
  static/
    aboutSuccess.php
    contactSuccess.php
 

Et si l'on ne souhaite pas avoir le suffixe par défaut Success, il suffit de retourner une chaine vide :

<?php
 
class contentActions extends sfActions
{
  public function executePage($request)
  {
    $this->setTemplate('static/'.$request->getParameter('page'));
 
    return '';
  }
}
 

symfony charge maintenant la template static/about.php.

Voici le contenu du répertoire templates/:

templates/
  static/
    about.php
    contact.php
 

Jouons avec le suffixe

Ajoutons un paramètre supplémentaire : Les pages statiques existent en deux formats, HTML et XML, et ces deux formats doivent pouvoir être disponibles aux utilisateurs.

Cela signifie que l'utilisateur peut maintenant accéder aux pages /static/about.html et /static/about.xml. Par défaut, si l'utilisateur ne précise pas d'extension, l'action doit retourner la version HTML.

Ajoutons l'extension en tant que paramètre de la requête dans la règle de routing :

page:
  url:   /static/:page.:extension
  param: { module: content, action: static, extension: html }
  requirements:
    extension: (html|xml)
 

Cerise sur le gâteau, on a ajouté une règle dans requirements afin de vérifier que l'extension est dans la liste des extensions disponibles.

Et voici la classe réécrite pour prendre en compte ce nouveau paramètre :

<?php
 
class contentActions extends sfActions
{
  public function executePage($request)
  {
    $this->setTemplate('static/'.$request->getParameter('page'));
 
    return '.'.$request->getParameter('extension');
  }
}
 

En accédant à la page /static/about (où /static/about.hml), symfony va charger la template static/about.html.php. Et si on demande la version XML de la page (/static/about.xml), symfony chargera la template static/about.xml.php.

Voici le contenu du répertoire templates/:

templates/
  static/
    about.html.php
    contact.html.php
    about.xml.php
    contact.xml.php
 

On peut également stocker les templates dans un sous-répertoire en fonction du format :

<?php
 
class contentActions extends sfActions
{
  public function executePage($request)
  {
    $this->setTemplate('static/'.$request->getParameter('extension').'/'.$request->getParameter('page'));
 
    return '';
  }
}
 

Voici le contenu du répertoire templates/:

templates/
  static/
    html/
      about.php
      contact.php
    xml/
      about.php
      contact.php
 

Dans la vraie vie, il faudrait bien évidemment changer également le content-type pour le format XML.

Voici une liste récapitulative de toutes les possibilités que nous avons vues :

// action
return $request->getParameter('page');
// template name
templates/staticabout.php
 
// action
$this->setTemplate($request->getParameter('page'));
// template name
templates/aboutSuccess.php
 
// action
$this->setTemplate('static/'.$request->getParameter('page'));
// template name
templates/static/aboutSuccess.php
 
// action
$this->setTemplate('static/'.$request->getParameter('page'));
return '';
// template name
templates/static/about.php
 
// action
$this->setTemplate('static/'.$request->getParameter('page'));
return '.'.$request->getParameter('extension');
// template name
templates/static/about.html.php
 
// action
$this->setTemplate('static/'.$request->getParameter('extension').'/'.$request->getParameter('page'));
return '';
// template name
templates/static/html/about.php
 

Discussion

#1 | João Barbosa | 2008-02-18 20:57
Very helpful specially the routing definition. Does executePage receives $request or one should do $this->getRequestParameter('page') for instance? Thanks.
#2 | Fabien | 2008-02-18 21:19
In symfony 1.1, executePage() receive $request by default. If you use symfony 1.0, you must use the $this->getRequestParameter().
#3 | Krešo Kunjas | 2008-02-21 09:08
So what parts of this article are 1.1 specific, except for $request->getParameter()
#4 | NiKo | 2008-03-11 15:23
Same question than Krešo :-)
#5 | Steffen | 2008-03-26 16:37
AFAIK the other 1.1 specific part ist the used "dot" seperator used in the routing. Prior to 1.1 only "slash" seperators were allowed here.
Les commentaires sur cette astuce sont fermés.
© 2007 Fabien Potencier  |  Powered by  Symfony Framework  |  Valid XHTML 1.0 Transitional