📚 | TP 5 : Templating engine
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
Partir de la correction du TP4 (copier/coller du dossier). lien
- Séance 5/TP5/
- public/
- ...
- framework/
View.php
- ÉtendResponse.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
- public/
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 :
<?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
À 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
<?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
<!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
<?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);
}
}