HomeDevLes systèmes de templates PHP

Les systèmes de templates PHP

Template est un mot anglais qui peut se traduire par modèle ou gabarit.

Template PHP : c’est quoi ?

Le principe est de séparer le code PHP de la mise en page HTML; Le code PHP dans un fichier, la mise en page contenant les balises HTML dans un autre fichier. On se retrouve alors avec, d’un coté, le script qui fait tout ce qu’il a à faire (ex: récupération de données dans une base de données, traitement…), et d’un autre coté, la mise en page avec des zones prédéfinies où seront placées les données générées par le script.

L’avantage évident est de pouvoir travailler uniquement sur la mise en page, sans modifier quoi que ce soit dans le code PHP et inversement, ou de diviser efficacement le travail à faire, le programmeur s’occupant uniquement de la partie scripting, et le designeur, de la mise en page.

Représentation simpliste du fonctionnement d’un système de template :

Représentation des templates PHP

Pour la suite de cet article/tutorial, nous travaillerons avec le système de templates du célèbre forum phpBB dont le fonctionnement est très proche de la phplib.

Affectation de variables à un template

Nous allons commencer par un exemple simple : Récupération d’un pseudo et d’une adresse email à partir d’une base de données puis affectation des données au template.

Voici le fichier test1.php :

<?php
  include('template.php');

  $connect = mysql_connect('localhost', 'root', '');
  mysql_select_db('database', $connect);

  $result = mysql_query("SELECT pseudo, email FROM table_users WHERE id = '1'");
  $row = mysql_fetch_array($result);

  /*
   * Nous admettrons ici que le pseudo obtenu est bobe
   * et l'email est bobe@domain.com
   */

  // on créé une nouvelle instance de la classe Template
  // et on indique en argument le chemin vers les modèles
  $template = new Template('./');

  // modèle à utiliser auquel on adjoint un nom arbitraire

  $template->set_filenames(array(
    'body' => 'template1.tpl'
  ));

  // Assignation des variables

  $template->assign_vars(array(
    'PSEUDO' => $row['pseudo'],
    'EMAIL'  => $row['email']

  ));

  // Affichage des données

  $template->pparse('body');
?>

Et voilà le fichier template1.tpl, le modèle que nous allons utiliser. Un fichier .tpl contient ni plus ni moins que du HTML.

<table border="1" cellpadding="2" cellspacing="0">
  <tr>
    <td>Le pseudo est&nbsp;: {PSEUDO}</td>
    <td>Adresse email&nbsp;: <a href="mailto:{EMAIL}">{EMAIL}</a></td>
  </tr>
</table>

Et maintenant, les explications. Commençons par le fichier test1.php.
Je passe sur les routines pour aller chercher les données dans la base de données, si vous lisez cet article, je pars du principe que vous savez vous y prendre.

$template = new Template('./');
On initialise la classe. La méthode Template prend comme argument facultatif le chemin vers les modèles. Ici, on indique que les modèles se trouvent dans le dossier courant
$template->set_filenames(array('body' => 'template1.tpl'));
on indique le modèle à utiliser, ici, template1.tpl, auquel on affecte le nom body
$template->assign_vars(array('PSEUDO' => $row['pseudo'], 'EMAIL' => $row['email']));
Le passage le plus important, on affecte les données aux variables qui se trouvent dans le fichier template1.tpl.
Littéralement; ça donne ça :
  • {PSEUDO} contiendra le contenu de la variable $row['pseudo']
  • {EMAIL} contiendra le contenu de la variable $row['email']
$template->pparse('body');
Le moteur de templates fait tous les traitements adéquats et affiche le résultat.

Voici ce que nous obtenons :

Test template PHP

Résultat il est vrai grossier, mais dù à la simplicité de l’exemple. A vous d’imaginer les possibilités d’un tel système. 🙂

Les blocks

Imaginons maintenant que vous vouliez afficher non pas un pseudo et une adresse email mais deux ! Simple me direz vous, il suffit de rajouter une cellule en dessous de l’autre dans le fichier template1.tpl, comme ceci :

<table border="1" cellpadding="2" cellspacing="0">
  <tr>
    <td>Le pseudo est&nbsp;: {PSEUDO}</td>
    <td>Adresse email&nbsp;: <a href="mailto:{EMAIL}">{EMAIL}</a></td>
  </tr>
  <tr>
    <td>Le pseudo est&nbsp;: {PSEUDO2}</td>
    <td>Adresse email&nbsp;: <a href="mailto:{EMAIL2}">{EMAIL2}</a></td>
  </tr>
</table>

Et d’affecter les valeurs correspondantes. Mais que faire lorsque on ne connait pas à l’avance le nombre de ligne pseudo/email que l’on va afficher ? C’est là que les blocs entrent en jeu.

Un bloc est une portion de code HTML comprise entre deux lignes de commentaires et qui sera affichée autant de fois que nécessaire.
Admettons que nous ne connaissons pas à l’avance le contenu de la table table_users. Voici ce qu’elle contiendra pour les besoins de l’exemple :

Données de la table table_users
id pseudo email
1 bobe bobe@domain.com
2 AllCoKe AllCoKe@domain2.net
3 toto toto@domain3.fr

Et maintenant, le fichier test2.php :

<?php
  include('template.php');

  $connect = mysql_connect('localhost', 'root', '');
  mysql_select_db('database', $connect);

  $result = mysql_query('SELECT pseudo, email FROM table_users');

  // on créé une nouvelle instance de la classe Template
  // et on indique en argument le chemin vers les modèles
  $template = new Template('./');

  // modèle à utiliser auquel on adjoint un nom arbitraire
  $template->set_filenames(array(
    'body' => 'template2.tpl'
  ));

  // Assignation des variables
  $template->assign_vars( array(
    'NB_USERS' => mysql_num_rows($result)
  ));

  //
  // Assignation des variables dans le block 'user'
  //
  while( $row = mysql_fetch_array($result) )
  {
      $template->assign_block_vars('user', array(
          'PSEUDO' => $row['pseudo'],
          'EMAIL'  => $row['email']

      ));
  }

  // Affichage des données
  $template->pparse('body');
?>

Et enfin, le modèle template2.tpl :

<table border="1" cellpadding="2" cellspacing="0">
  <tr>
    <td colspan="2"> Il y a {NB_USER} membres </td>
  </tr>
  <!-- BEGIN user -->
  <tr>
    <td>Le pseudo est&nbsp;: {user.PSEUDO}</td>
    <td>Adresse email&nbsp;: <a href="mailto:{user.EMAIL}">{user.EMAIL}</a></td>
  </tr>
  <!-- END user -->
</table>

Le modèle template2.tpl pour commencer : Il contient à peu de choses près la même chose que dans l’exemple du premier paragraphe. Nous avons rajouté une cellule où nous indiquerons dynamiquement le nombre de membres présents dans la table table_users (variable {NB_USER}).

La différence essentielle est que nous avons défini le bloc user, et ceci à l’aide de lignes de commentaires. Schématiquement, un block est construit de cette façon :

<!-- BEGIN nom_du_block -->

Les différentes balises html qui constituent le bloc

<!-- END nom_du_block -->

Le commentaire de déclaration de début de bloc doit être seul sur sa ligne, de même que le commentaire de fin de bloc. Les variables incluses dans un bloc portent le nom du bloc comme préfixe, ici : {user.PSEUDO} et {user.EMAIL}.

Dans le fichier test2.php, nous avons assigné le résultat de mysql_num_rows($result) dans la variable {NB_USER}. Puis dans la boucle while, nous utilisons la méthode assign_block_vars, membre de la classe Template. Le premier argument de cette méthode est le nom du bloc concerné, ici user, le deuxième argument est le tableau contenant les variables du modèle et leur contenu.

A chaque passage dans la boucle, le bloc user est répété, avec les nouvelles valeurs qui sont assignées aux variables du modèle.

Voilà ce que ça donne :

Résultat de notre test PHP

Les blocks imbriqués

Allons encore plus loin dans l’utilisation du système de templates et étudions le cas des blocks imbriqués.
Les blocks imbriqués impliquent quelques règles strictes à respecter :

  • Deux blocs imbriqués ne peuvent pas se chevaucher
  • Le nom d’un bloc doit porter le nom du bloc parent en préfixe (s’il y a lieu) lors de la déclaration à l’aide de la méthode assign_block_vars()
  • Les variables doivent porter en préfixe de leur nom le nom du bloc duquel elles font partie ainsi que des blocs parents

Exemple d’imbrication incorrecte, les blocs se chevauchent :

Il y a {NB_USER} membres <br>
<table border="1" cellpadding="2" cellspacing="0">
  <!-- BEGIN user -->
  <tr>
    <td>Le pseudo est&nbsp;: {user.PSEUDO}</td>
    <td>Adresse email&nbsp;: <a href="mailto:{user.EMAIL}">{user.EMAIL}</a></td>
    <!-- BEGIN id -->
    <td>ID&nbsp;: {user.id.IDENTIFIANT}</td>
    <!-- END user -->
  </tr>
  <!-- END id -->
</table>

Exemple d’imbrication correcte, le bloc id est inclus dans le bloc user (template3.tpl) :

Il y a {NB_USER} membres <br>
<table border="1" cellpadding="2" cellspacing="0">
  <!-- BEGIN user -->
  <tr>
    <!-- BEGIN id -->
    <td>ID&nbsp;: {user.id.IDENTIFIANT}</td>
    <!-- END id -->
    <td>Le pseudo est&nbsp;: {user.PSEUDO}</td>
    <td>Adresse email&nbsp;: <a href="mailto:{user.EMAIL}">{user.EMAIL}</a></td>
  </tr>
  <!-- END user -->
</table>

Voici le fichier test3.php :

<?php
  include('template.php');

  $connect = mysql_connect('localhost', 'root', '');
  mysql_select_db('database', $connect);

  // cette fois, on récupère aussi l'id de la ligne.
  $result = mysql_query('SELECT id, pseudo, email FROM table_users');

  // on créé une nouvelle instance de la classe Template
  // et on indique en argument le chemin vers les modèles
  $template = new Template('./');

  // modèle à utiliser auquel on adjoint un nom arbitraire
  $template->set_filenames(array(
      'body' => 'template2.tpl'
  ));

  // Assignation des variables
  $template->assign_vars(array(
      'NB_USERS' => mysql_num_rows($result)
  ));

  // on récupère la variable $mode.
  $mode = $_GET['mode'];

  //
  // Assignation des variables dans le block 'user'
  //
  while( $row = mysql_fetch_array($result) )
  {
      $template->assign_block_vars('user',array(
          'PSEUDO' => $row['pseudo'],
          'EMAIL'  => $row['email']

      ));

      // Si mode contient la chaine display, on affiche l'id du membre.
      if( $mode == 'display' )
      {
          $template->assign_block_vars('user.id',array(
              'IDENTIFIANT' => $row['id']

          ));
      }
  }

  // Affichage des données
  $template->pparse('body');
?>

Le résultat si la variable mode, contenant display n’est pas passée dans l’URL :

Résultat de notre test PHP

Et si la variable mode, contenant display est passée dans l’URL :

Résultat de notre test PHP

Imbrication des templates

Vous pouvez avoir besoin d’insérer dans un modèle le résultat du traitement d’un autre modèle. Ceci est possible. Il vous suffit pour ça d’appeller la méthode assign_var_from_handle() au lieu de pparse().

Cette méthode prend deux arguments, le premier est le nom de la variable dans le modèle de destination, le deuxième est le nom que vous avez donné à votre autre modèle lors de l’appel à la méthode set_filenames().

Petit exemple :

<?php
  include('template.php');

  // on créé une nouvelle instance de la classe Template
  // et on indique en argument le chemin vers les modèles
  $template = new Template('./');

  // modèle à utiliser auquel on adjoint un nom arbitraire
  $template->set_filenames(array(
      'body' => 'template.tpl'
  ));

  //
  // On assigne les variables que l'on veut à notre modèle
  //

  // Deuxième modèle
  $template->set_filenames(array(
      'body2' => 'template2.tpl'
  ));

  //
  // On assigne les variables que l'on veut à notre modèle
  //

  //
  // On insère le résultat du modèle 'body2' dans le premier modèle
  //
  $template->assign_var_from_handle('RESULTAT_BODY2', 'body2');

  //
  // On affiche notre premier modèle la variable {RESULTAT_BODY2}
  // dans le modèle aura été remplacée par le résultat du
  // traitement du deuxième modèle
  //
  $template->pparse('body');
?>

De nombreux autre systèmes de templates existent, tels Smarty ou encore Modelixe.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.