Mémos

M é m o - l a b .

Modèle Vue/Contrôleur – Approche

Il est possible de structurer son code, notamment de séparer les vues du reste du code dédié aux contrôleurs, ceux-ci s s’occupant de récupérer les données à envoyer à la vue. Les templates php utilisés classiquement sous WP deviennent des contrôleurs. Ils ne contiennent que du code php et ne s’occupent plus de l’affichage qui lui, est géré en html par les vues. Se pose alors le problème de l’affichage des données dynamiques envoyées par les contrôleurs. La solution est d’utiliser un pont permettant de transmettre les données des contrôleurs vers la vue. Pour cela, nous utilisons le moteur de template twig (outil natif du framework symfony).

Dans un premier temps, nous installons le moteur de template twig. Depuis une console, se placer au niveau du dossier de notre thème personnalisé et lancer les 2 commandes suivantes (la première crée le fichier composer.json et la deuxième installe twig) :
composer init
composer req twig/twig

Dans functions.php, appeler l’autoload de composer : require_once ‘vendor/autoload.php’;

1 page homepage est créée et définie comme page d’accueil. Le template php retenu par le core de WP est front-page.php (cf chapitre Template hierarchy) qui dans le cadre de ce chapitre joue le rôle du contrôleur. La vue appelée par ce contrôleur est appelée front-page.html.twig. Cette vue affiche la liste des articles. Le titre de l’article est affiché sous forme de lien. Le template dédié à l’affichage d’un seul article étant single.php, le click sur ce lien appellera le contrôleur single.php qui cible la vue single.html.twig.
Les vues se trouvent dans le dossier views.
Le chargement et les réglages de twig se font dans le contrôleur Controller.php dont héritent les templates contrôleurs.
Les fichiers header.php et footer.php sont remplacés par le fichier base.html.twig. La classe WP_Twig_Extension permet de définir les fonctions php utilisées dans ces 2 fichiers php afin de pouvoir les intégrer dans le fichier twig base.html.twig.

La compréhension par le code





Controller.php

<?php
namespace App;

class Controller
{
	protected $twig;

	public function __construct() {
		$loader = new \Twig\Loader\FilesystemLoader(get_template_directory() .'/views');
		$twig = new \Twig\Environment($loader, [
			'debug' => true,
		    'cache' => get_template_directory() .'/twig/cache',
		]);
		// Permet l'tilisation de dump par exemple
		$twig->addExtension(new \Twig\Extension\DebugExtension());
		// Custom twig extensions
		$twig->addExtension(new \App\Config\WP_Twig_Extension());

		$this->twig = $twig;
		echo $this->index();
	}

	public function render($view, $parameters) {
		return $this->twig->render($view, $parameters);
	}
}
?>



front-page.php

<?php
namespace App;

class FrontpageCtrl extends Controller
{
	public function index() {
		$posts = get_posts([
			'post_type' => 'post',
			'posts_per_page' => -1
		]);

		return $this->render('frontpage.html.twig', [
			'posts' => $posts
		]);
	}
}

new FrontpageCtrl();
?>



single.php

<?php
namespace App;

class SingleCtrl extends Controller
{
	public function index() {
		$post = get_post(get_the_id());

		return $this->render('single.html.twig', [
			'post' => $post
		]);
	}
}

new SingleCtrl();
?>



config/WP_Twig_Extension.php

<?php
namespace App\Config;

class WP_Twig_Extension extends \Twig\Extension\AbstractExtension
{
	public function getFunctions()
    {
        return [
            new \Twig\TwigFunction('language_attributes', [$this, 'language_attributes']),
            new \Twig\TwigFunction('charset', [$this, 'charset']),
            new \Twig\TwigFunction('wp_head', [$this, 'wp_head']),
            new \Twig\TwigFunction('body_class', [$this, 'body_class']),
            new \Twig\TwigFunction('wp_footer', [$this, 'wp_footer']),
        ];
    }

    public function language_attributes() {
    	return language_attributes();
    }
    public function charset() {
    	return bloginfo('charset');
    }
    public function wp_head() {
    	return wp_head();
    }
    public function body_class() {
    	return body_class();
    }
    public function wp_footer() {
    	return wp_footer();
    }
}
?>

fichiers twig (vues) :





views/base.html.twig

<!DOCTYPE html>
<html {{ language_attributes() }}>
<head>
	<meta charset="{{ charset() }}">
	<title>Document</title>

	{{ wp_head() }}
</head>
<body {{ body_class() }}>
	<main role="main">
		{% block body %}{% endblock %}
	</main>

	{{ wp_footer() }}
</body>
</html>



views/frontpage.html.twig

{% extends 'base.html.twig' %}

{% block body %}
	{% for post in posts %}
		<a href="{{ post.guid }}"><h1>{{ post.post_title }}</h1></a>
		<p>{{ post.post_content|raw }}</p>
	{% endfor %}
{% endblock %}



views/single.html.twig

<h1>{{ post.post_title }}</h1>
<p>{{ post.post_content|raw }}</p>