Skip to main content

📚 | TP 5 : Templating engine

info

Différemment des TD, les TP doivent s'effectuer seul. Ainsi, la réponse que vous trouverez à la problématique peut différer d'un étudiant à l'autre.

Faire le TP

1. Créer la structure du projet

warning

Partir de la correction du TP4 (copier/coller du dossier). lien

  • Séance 5/TP5/
    • public/
      • ...
    • framework/
      • View.php - Étend Response.php - Classe PHP représentant une vue/template
        • $file - String - Nom du template.
        • $data - Array - Variables à transférer dans le template.
        • Autres éléments de Response.php...
        • render() - Fonction - Permet de faire le rendu du moteur de templating. Insérer le code suivant : Fonction render()
      • ...
    • controllers/
      • MyViewController.php - Classe PHP qui renverra des vues.
      • Autres contrôleurs...
    • views/
      • Footer.html - Fichier HTML.
      • MyTemplate.dacs - Fichier/template HTML comportant des éléments de templating.
      • Autres fichiers HTML/dacs

2. Ajouter un autoloader

Un autoloader est un fichier qui charge automatiquement toutes les classes PHP de votre code, simplifiant ainsi leur import et leur utilisation.

À la racine de votre projet, ajouter ce fichier :

autoloader.php
<?php

/* Code from internet, automatically load classes if they are currently not loaded */

// https://www.php.net/manual/en/language.oop5.autoload.php

spl_autoload_register(function ($className) {
$filename = __DIR__ . DIRECTORY_SEPARATOR . str_replace('\\', '/', $className) . '.php';
if (file_exists($filename)) require_once($filename);
});

Pour utiliser l'autoloader, il suffira d'ajouter cette ligne au tout début de votre index.php :

// Import the autoloader, which loads all the namespaces and classes
require(__DIR__ . '/../autoloader.php');

3. Lancer le serveur

Une fois à la racine de votre projet /Séance 5/TP5/, il faut utiliser la commande suivante :

php -S localhost:8080 -t public
warning

À noter que le dossier servi est public et non TP5. Cela permet d'avoir des accès utilisateurs différents, mon dossier public va être accessible par quasi-tout me monde (774). Là où mon dossier TP4 n'est accessible que par l'utilisateur courant (700).

Cependant, cela n'a pas d'importance dans notre TP

4. Fonction render() de View.php

public function render(): string {
$file = file_get_contents('../views/' . $this->file);

$file = str_replace("{{", "<?php", $file);
$file = str_replace("}}", "?>", $file);

$file = preg_replace("/@echo\(\s*(.+)\s*\)/", "<?php echo($1); ?>", $file);

$file = preg_replace("/@if\(\s*(.+)\s*\)/", "<?php if($1): ?>", $file);
$file = preg_replace("/@elseif\(\s*(.+)\s*\)/", "<?php else if($1): ?>", $file);
$file = str_replace("@else", "<?php else: ?>", $file);
$file = str_replace("@endif", "<?php endif; ?>", $file);

$file = preg_replace("/@foreach\(\s*(.+)\s*\)/", "<?php foreach($1): ?>", $file);
$file = str_replace("@endforeach", "<?php endforeach; ?>", $file);

$file = preg_replace("/@require\(\s*(.+)\s*\)/", "<?php require('../views/' . $1); ?>", $file);

ob_start();
extract($this->data);

eval('?>' . $file);

$content = ob_get_contents();
ob_end_clean();

return $content;
}

5. Exemple de vue dans un contrôleur

Nouvelle route

routes.php
<?php

// Contain all the routes
return [
// Create a new GET route linked to the /api route
new Route(Method::GET, '/api', IndexController::class, 'index'),
new Route(Method::GET, '/index', ViewController::class, 'index')
];

Ma vue

index.dacs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Index</title>
</head>
<body>
<p>Page de test</p>
<p>{{ echo $nom }}</p>

@if($ma_var == 2)
<p>ma var est égale à 3!!!</p>
@else
<p>ma var n'est pas égale à 3</p>
@endif

<ul>
@foreach($items as $item)
<li>élément : @echo($item)</li>
@endforeach
</ul>

<footer>
@require("footer.html")
</footer>
</body>
</html>

Mon contrôleur

MyViewController.php
<?php

namespace controllers;

use framework\Response;
use framework\ResponseType;
use framework\View;

/**
* Basic HTTP controller
*/
class ViewController {
/**
* Route linked to /index
*
* @param array $request
* @return Response
*/
function index(array $request) : Response {
$vars = [
"nom" => "Julien",
"ma_var" => 3,
"items" => [
1,
2
]
];

// Comme View étend Response, il peut ainsi être utilisé comme tel
return new View("index.dacs", $vars);
}
}
X

Graph View