Un système de template simple et efficace avec les fonctions natives de php

Un système de template simple et efficace avec les fonctions natives de php

Introduction

Voilà, j'ai voulu simplement mettre en oeuvre un système de template avec juste les fonctions native de php. Beaucoup se donnent la peine de coder de gros systèmes de template alors que leur application est moyenne. D'autres s'adonnent à la même pratique sans bien comprendre la notion de template. Et c'est ainsi que m'est venue l'idée d'utiliser les fonctions que propose déjà php et qui font la quasi-totalité de ce qu' un moteur de template de renommée peut faire.

Le véritable challenge pour un codeur en PHP n'est pas le code mais le design et la mise à jour de celui-ci ou de son code.

Mais comment ? C'est moi qui l'ai écrit, comment cela sera difficile ?

Le pire ennemi est ici le « pèle mêle » c'est à dire le mélange du code html au php.

Vous verrez qu'à la longue vous ne pourrez plus différencier la raison pour laquelle telle portion du code ou telle autre est là ou ne l'est pas.

Mais le deuxième point le plus crucial c'est la mise à jour du design d'un site. Dans le cas d'un « pèle mêle », on sera obligé de mettre à niveau le code php en même temps que celui du html, ce qui s'avère un peu délicat dans le cas d'une grosse application.

Le système de Template, voilà notre sauveur. Mais qui est il et à quoi sert-il ?

Un système de Template est un système permettant de scinder le code d'une page en deux, la partie html et la partie php. Ce système présente plusieurs avantages :

  • Il permet de travailler sur le design sans modifier le code ou l'inverse.

Modifier le code sans se soucier du design

  • Aviez-vous rêvé de laisser le choix du design à l'utilisateur ? Avec le système de template, il est possible d'avoir plusieurs design pour un même site.
  • sans oublier qu'avec celui-ci, vous pourrez faire un système de gestion de cache. Je n'aborderai pas le sujet ici ; ceci pourra faire l'objet d'un autre tutoriel.

Les Fonctions PHP utilisées

Les fonctions de bufferisation

On n'utilisera que les fonctions de bufferisation principales à savoir :

  • ob_start () : c'est la première fonction à appeler. A quoi elle sert ? Eh bien, on ne peut pas effectuer d'opérations sur le buffer sans instruire le serveur de suspendre la bufferisation de sortie. En d'autres termes, elle dit au serveur "n'affiche rien dans le navigateur tant qu'on te l'a pas demandé". Donc, même si vous faites un echo ou print après cette fonction vous ne verrez rien a l'écran.
  • Si la fonction ob_start () démarre la bufferisation et empêche l'affichage de tous echo, ob_flush () permet elle d'envoyer les données au navigateur. On pourra donc faire tout ce que l'on veut avec le contenu du buffer avant de l'afficher.
  • Temporiser ou bufferiser implique la sauvegarde de notre page. Un conseil donc, veiller toujours à vider le buffer ok mais comment fait-on ? il faut dire « abracadabra » et hop ! ob_clean ()
  • Et maintenant qu'est-ce qui nous permettra de récupérer le contenu du buffer afin de le modifier à notre guise ? c'est la fonction ob_get_contents ()

Note : il existe des fonctions similaires à ob_clean () et ob_flush () qui sont ob_end_clean () et ob_end_flush () qui en plus de faire la même chose que ob_clean () et ob_flush () mettent fin à la bufferisation.

Exemple d'utilisation

< ?php
// On démarre la bufferisation
ob_start () ;
// On affiche quelque chose
echo `j'ai déjà démarré la bufferisation' ;
// On récupère le contenu du buffer
$buffer = ob_get_content () ;
// Notre traitement ici

// On a récupéré le contenu du buffer dans $buffer, on peut l'effacer
ob_clean () ;
// On envoie le tout au navigateur
ob_flush () ;
?>

Les autres fonctions utilisées

Les autres fonctions, je crois que tout le monde les connaît mais qui ne veut pas se rafraichir la mémoire.

split () cette fonction permet d`exploser une chaîne de caractères en tableaux ; elle prend en paramètre le critère pour lequel on veut scinder la chaîne.

Imaginez par exemple que vous disposez d'un moteur de recherche sur votre site et vous utilisez les fonctionnalités « or » ou « and » pour la comparaison. On ne dira pas à l'utilisateur de saisir le premier puis le deuxième mot ainsi de suite mais naturellement il va séparer les mots par un espace. Et là, avec split () on pourra récupérer les différents mots tapés dans le champ.

< ?php
$mot = $_POST [`mot'] ;
// Notre critère pour scinder la chaîne est l'espace que l'utilisateur a mis entre les mots
$mots = split (` `,$mot) ;
//maintenant $mots est un tableau contenant tous les mots saisis
?>

Donc, c'est un tuto dans un autre pour les codeurs de moteur de recherche. Voilà une idée.

str_replace () c'est la fonction de remplacement la plus facile. Il est conseillé de l'utiliser si on veut faire des remplacements simples. Ah bon mais qu'est-ce qu'elle remplace ? On va utiliser notre split () sur str_replace (), ce qui donne string replace, ou en français facile « remplacer chaîne ». Ce qui implique qu'on peut avec cette fonction remplacer une chaîne dans une chaîne par une autre chaîne. Voilà un exemple pour ne pas rester chaînés

< ?php
//notre chaîne initiale ;
$str_intiale = `hello {str_remplacer} how are you ?`;
// ce que l'on veut ici, c'est remplacer {str_remplacer} par devil_may_cry. 
//Notez bien cette notation car c'est elle qu'on utilisera dans notre système de Template
$str_finale = str_replace (`{str_remplacer}','devil_may_cry',$str_initiale) ;
// on affiche
echo `avant modification '.$str_initiale. `<br>' ;
echo `après modification '.$str_finale. `<br>' ;
?>

vous aurez à l'écran :
avant modification hello {str_remplacer} how are you ?
après modification hello devil_may_cry how are you ?

file () : c'est une fonction qui permet de récupérer rapidement le contenu d'un fichier. Elle retourne un tableau dont chaque ligne correspond à une ligne du fichier.

Attention, cette fonction tient compte des indentations du fichier. On verra dans le point suivant comment exploiter ce tableau.

implode () : elle permet de concaténer les éléments d'un tableau. Elle prend en paramètre la chaîne de jointure et le tableau. C'est avec elle qu'on va exploiter le tableau retourné par file ()

ca y'est, c'en est fini pour les révisions ; on retrousse les manches

Les Codes

Les pages dont on aura besoin sont :
Template_func.php // c'est là qu'on mettra toutes nos fonctions de gestion du template
Index.php // c'est notre page principale. C'est là que se fera l'appel de template_func.php en tout début de page ;
Test.html // le template

Note : on suppose que tous ces fichiers se trouvent dans le même répertoire

Un peu de théorie

En temps normal, on traite et on affiche en même temps, alors que là, on va tout afficher. « afficher » veut dire ici qu'on envoie nos echo vers le buffer et non vers la sortie standard (l'écran) ; on effectue ensuite nos traitements mais seul le résultat final sera visible à l'écran naturellement après que l'on en aura donné ordre.

Pour aboutir au résultat souhaité, il faudra respecter les conventions ci-dessous. N'hésitez pas à les relire afin de comprendre pourquoi telle ou telle chose est là ou ne l'est pas.

Ces conventions ne sont là que pour un meilleur suivi du tutoriel mais dès que vous aurez saisi le truc, libre à vous d'écrire vos propres conventions.

  • On nommera constante toute chaîne contenue dans le Template sous la forme « {nom_constante} »
  • On nommera block tout contenu du Template devant être dupliqué et chaque block comportera ses propres constantes
  • Tout block doit être délimité de la façon suivante :
< !-- BEGIN nom_du_block -->
// ici le contenu du block
< !-- END nom_du_block -->

template_func.php

Ce script contient 3 fonctions

Init ($file) : cette fonction prend en paramètre le fichier Template qui va se charger de l'afficher
Set_var ($varray) : cette fonction se charge de remplacer une constante n'appartenant pas à un block par sa valeur. Elle prend en paramètre un tableau associatif de la forme $varray = array (`const1'=>'valconst1','const2'=>'valconst2','constN'=>'valconsN') ;
set_varray ($blockname,$varray) : celle-ci se charge de remplacer les constantes d'un block. Elle prend en paramètre le nom du block $blockname ainsi que les différentes valeurs des constantes du block.

$varray est de la forme :
$varray [$cpt] = array (`const1'=>'valconst1','const2'=>'valconst2','constN'=>'valconsN') ;
$cpt est un compteur on verra par la suite comment il marche.

Voici les codes sources de ces trois fonctions

Init ($file)

<?php
//on démarre la bufferisation
ob_start() ;
function init ($file) {
    // on ouvre le fichier en lecture et on récupère son contenu
    $fp = file($file);
    // On réunit le contenu du fichier dans $fileContent
    $fileContent = implode("",$fp);
    // On affiche le contenu mais celui ci ne sera pas visible il sera bufferisé
    echo $fileContent;
}

set_var($varray)

function set_var($varray) {
    // On récupère le contenu du buffer avec ob_get_contents
    $buffer = ob_get_contents();
    //$varray représente un tableau sous la forme nom_variable=>valeur_variable
    // On parcourt alors $varray avec une boucle foreach
    foreach ($varray as $key=>$val) {
        // On utilise str_replace pour remplacer la constante par sa valeur
        $buffer = str_replace('{'.$key.'}',$val,$buffer);
    }
    // Efface le contenu du buffer
    ob_clean();
    // et on envoie le nouveau contenu
    echo $buffer;
}

Set_varray($blockname,$varray)

function set_varray($blockname,$varray) {
    // On récupère le contenu du buffer avec ob_get_contents
    $buffer = ob_get_contents();
    // on doit récupérer le contenu du block et lui assigner ces valeurs
    // il y a plusieurs méthodes pour le faire mais je ne vais pas compliquer les choses
    // on utilisera split
    // Avec le premier split, on ne récupère que le contenu du block délimité à la fin
    // par le tag <!-- End nom_du_block --> c'est là qu'intervient
    // notre deuxième split pour ne laisser que le contenu du block;
    $block = split("<!-- BEGIN ".$blockname." -->",$buffer);
    $blockf = split("<!-- END ".$blockname." -->",$block[1]);
    // on assigne le contenu du block dans $blockContent
    $blockContent = $blockf[0];
    // On doit maintenant marquer l'emplacement du block dans le buffer
    // pour dire que c'est là qu'on va revenir pour replacer les donnes du block
    $buffer = str_replace("<!-- BEGIN ".$blockname." -->".$blockContent."<!-- END ".$blockname." -->","{".$blockname."}",$buffer);
    // on remplace maintenant les valeurs du block
    // On parcourt alors $varray avec une boucle for d'abord pour gérer chaque itération, ensuite avec une boucle foreach pour remplacer les constantes par leur valeur
    $max = count($varray);
    $content = $blockContent;
    for ( $i = 0; $i < $max ;$i++ ) {
         foreach( $varray[$i] as $key=>$val ) {
             // On utilise str_replace pour remplacer la constante par sa valeur
             $content = str_replace('{'.$key.'}',$val,$content);
        }
        //on vérifie si on doit concaténer à nouveau le block ou pas
        if ( $i+1 < $max ) {
            // On concatène à nouveau le block
            $content .= $blockContent;
       }
   }
// Toutes les variables ont été correctement assignées
// On les replace dans notre variable $buffer
$buffer = str_replace("{".$blockname."}",$content,$buffer);
// Efface le contenu du buffer
ob_clean();
// et on envoie le nouveau contenu
echo $buffer;
}

test.html

C'est le fichier template qu'on va utiliser. Il ressemble à quelque chose comme ca

<html>
<head>
    <title>Mon Premier gestionnaire de template</title>
</head>

<body>
    <div>
        Un tutoriel sur la gestion des templates par {AUTHOR_NAME} publié sur le site
        {SITE_NAME} que vous pouvez visiter à l'adresse {SITE_ADDRESS}
    </div>
    <!-- BEGIN LIST_TUTO -->
    <div>
        <p>
            <span>{TUTO_TITLE}</span>
            <span>Format {TUTO_FORMAT}</span>
            <span>Consultés {TUTO_NBREAD} fois</span>
        </p>
    </div>
    <!-- END LIST_TUTO -->
</body>
</html>

Ce template comporte donc 3 constantes qui sont {AUTHOR_NAME} {SITE_NAME} et {SITE_ADDRESS}. Et pour les remplacer par leur valeur, on fera appel à set_var ()

Il contient aussi un block « LIST_TUTO » qui comporte les constantes > {TUTO_TITLE} {TUTO_FORMAT} et {TUTO_NBREAD} ; ici set_var () ne fera pas l'affaire, on fera donc appel à set_vararray () ;

index.php

C'est le script de base. C'est lui qui fera appel à toutes les fonctions

< ?php
//on inclut notre gestionnaire de template
include 'template_func.php' ;

//on initialise le template
Init('test.html') ;

//on remplace les constantes qui ne sont pas dans des blocks
// pour faciliter l'écriture, on déclare un tableau infos avec les constantes comme clefs et leur valeur
$infos = array('AUTHOR_NAME'=>'devil_may_cry', 'SITE_NAME'=>'phpcs.com', 'SITE_ADDRESS'=>'http://www.phpcs.com');
set_var($infos);

// on remplace pour les blocks maintenant
// mais il faut impérativement créer un tableau avec toutes les constantes et leur valeur en indiquent le nombre d'itérations
$infos[0] = array('TUTO_TITLE'=>'tuto1','TUTO_FORMAT'=>'pdf','TUTO_NBREAD'=>'5');

$infos[1] = array('TUTO_TITLE'=>'tuto2','TUTO_FORMAT'=>'doc','TUTO_NBREAD'=>'0');
$infos[2] = array('TUTO_TITLE'=>'tuto3','TUTO_FORMAT'=>'html','TUTO_NBREAD'=>'2');

//pour remplacer dans le block « LIST_TUTO » on fait
$tp->set_varray('LIST_TUTO',$infos);
//on peut utiliser ici ob_clean() ensuite ob_end_flush()
ob_clean();
ob_end_flush ();
?>

Conclusion

Et voilà notre gestionnaire de template, simple et efficace. Mais la solution exposée ici n'est qu'une manière simple pour faire comprendre le système de template. Ce n'est en aucun cas une solution adéquate pour un site web ou une grosse application.

J'ai skippé aussi plusieurs étapes comme la sécurité et la consolidation du code. Mais comme je l'ai dit, j'ai juste essayé de mettre en oeuvre une technique simple pour que le code soit à la portée de tous. Vous pouvez prendre le temps d'améliorer les scripts pour mieux saisir les notions utilisées ici et enfin essayer de le modéliser. A ce moment vous disposerez d'un vrai système de template car sans la POO votre gestionnaire de template restera dans la zone rouge

Si vous avez des remarques ou des questions, je serai là pour ça.

Rejoignez-nous