Dans quel ordre se charge WordPress ?

C’est assez rigolo de se rendre compte que peu de « développeurs » vont parcourir le code de leur outil. Et pourtant c’est bien là qu’est le plus bel apprentissage !

Pourquoi partir du fichier index.php ?

Je ne serais pas exhaustif sur le sujet car il peut se cacher plein de configurations différentes en fonction des types de serveur que vous utilisez Apache, NGINX, IIS ou autre. Hormis si vous avez modifier les réglages par défaut, par convention les fichiers qui sont appelés en premiers sont les fichiers qui se nomment « index » suivi de l’extension de la technologie que vous utilisez.

WordPress étant codé en PHP, ça devient donc logique que le fichier index.php situé à la racine du CMS soit chargé en premier.

Ouvrons-le et faisons abstraction des commentaires, il ne reste que 2 lignes de code !

<?php
/**
 * Front to the WordPress application. This file doesn't do anything, but loads
 * wp-blog-header.php which does and tells WordPress to load the theme.
 *
 * @package WordPress
 */

/**
 * Tells WordPress to load the WordPress theme and output it.
 *
 * @var bool
 */
define( 'WP_USE_THEMES', true );

/** Loads the WordPress Environment and Template */
require __DIR__ . '/wp-blog-header.php';

Cette 1ère ligne vient définir si dans son exécution WordPress va devoir charger un thème et l’afficher ou non.

define( 'WP_USE_THEMES', true );

Dans quel cas ça ne sert à rien d’utiliser les thèmes de WordPress me direz-vous ?

Et bien plus de fois que l’on ne croit… Forcément tant qu’on est pas tombé sur ces cas ça tombe pas encore sous le sens.

Le 1er que je vois et qui a pas mal le vent en poupe au moment ou j’écris ces lignes c’est…

Utiliser WordPress en mode Headless

Plus besoin de charger de thème si ce n’est pas WordPress lui même qui s’occupe de charger le front. On se retrouve dans le cas ou WordPress est utilisé comme une API et un client, souvent codé en JavaScript, va venir consommer la data de cette API.

Enfin un autre moins commun mais qui a son utilité tout de même.

Utiliser WordPress Comme un outil interne

Par exemple, je veux gérer mes factures depuis WordPress (et pourquoi pas après tout…) je créé un multisite, un sous-domaine, je branche les deux. Je crée un type de contenu personnalisé pour créer et télécharger mes factures au format PDF. Tout est géré en étant connecté pas besoin de front. Ce sont des cas bien particulier surtout adapté sur des plus grosses structure avec des mécaniques métier propriétaire ou bien spécifique.

Y’a tant de choses à dire grâce a une ligne de code que ça en devient inquiétant pour la suite de l’article…


Passons à la deuxième si vous le voulez bien car je vous trouve bien dissipé, on avance pas beaucoup !

require __DIR__ . '/wp-blog-header.php';

Ce fichier charge les différents fichiers nécéssaire au bon fonctionnement de WordPress il mérite donc qu’on s’attarde un peu dessus.

WordPress charge son environnement via wp-blog-header.php

Encore du bol ce fichier ne contient pas tant de lignes que ça à comprendre.

$wp_did_header est une variable globale créée par WordPress, elle permet de vérifier si le CMS a déjà renvoyé un header ou non. Forcément la 1ère fois qu’on passe dans ce fichier c’est pas le cas d’où le fait qu’elle passe à true pour invalider la condition au prochain passage.

Derrière, ce fichier s’occupe de charger les coulisses de WordPress en 3 temps :

  • D’abord, importer la bibliothèque de fonctions disponibles dans WordPress via wp-load.php ;
  • Ensuite, exécuter la requête de l’utilisateur grâce à la fonction wp() ;
  • Puis, charger le résultat en front via le thème actif dans le back-office de WordPress via template-loader.php.

Détaillons ensemble tout ce cheminement.

Charger les fonctionnalités de WordPress via wp-load.php

Ce fichier commence a se gâter car il gère 2 cas : est-ce que le fichier wp-config.php existe ou non ?

Dans le cas ou ce fichier n’existe pas, la démarche est la suivante : WordPress ne connait pas encore les informations de connexion à la base de données, il ne peut donc pas communiquer avec. C’est alors que le processus d’installation du CMS se lance.

À quelques dépendances de fonctions près, le gros du morceau se situe dans /wp-admin/setup-config.php ça fera sans doute l’objet d’un autre article. Dans les avancées de l’installation, WordPress duplique le fichier wp-config-sample.php et remplace les valeurs de certains constantes par celle que vous lui aurez fournit.

Le fichier wp-config.php mérite un article à part entière qu’on prendra le temps de décortiquer lorsqu’on se sera remis de celui là. Dans les grandes lignes, il s’agit de toutes les variables d’environnement pour se connecter à la BDD ou déterminer comment seront chiffrer certaines information grâce aux Salt.

On ne peut pas continuer à charger WordPress si il n’y a pas ces informations.

Maintenant que ce fichier existe voyons le deuxième cas.

Récupérer les variables d’environnement du wp-config.php

Ce fichier est indispensable au bon fonctionnement du CMS. Petite astuce sécurité, vous pouvez déplacer votre fichier wp-config.php dans le dossier parent (qui lui n’est pas censé être accessible via une URL), WordPress saura tout de même le charger. Ce qui est intéressant en réalité ce sont les dernières lignes de ce fichier.

Celles-ci :

/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';
<?php
/**
 * Loads the WordPress environment and template.
 *
 * @package WordPress
 */

if ( ! isset( $wp_did_header ) ) {

	$wp_did_header = true;

	// Load the WordPress library.
	require_once __DIR__ . '/wp-load.php';

	// Set up the WordPress query.
	wp();

	// Load the theme template.
	require_once ABSPATH . WPINC . '/template-loader.php';

}

Pourquoi ? Vraiment ?

Ce n’est que maintenant que WordPress se charge !

Et je ne suis pas en train de vous dire que vous vous êtes taper 30 minutes de lecture pour enfoncer une porte ouverte. C’est plutôt que la partie la plus intéressante à mon sens est à venir.

Instancier WordPress avec wp-settings.php ?

Je vais éviter de vous faire des copier/coller de code de ce fichier car c’est indigeste. C’est à ce moment là que les adeptes de la Programmation Orientée Objet se retournent dans leur tombe…

Jusque là on pouvait admettre que chaque fichier n’avait qu’une seule responsabilité et encore… Mais là, c’est la cata.

Pour ne pas rentrer dans le détails de chaque ligne le fichier wp-settings.php sert à :

  • Définir des variables globales
  • Checker les compatibilités de versions de PHP et MySQL
  • Inclure tous les fichiers nécéssaire au bon fonctionnement de WordPress
  • Initialiser des constantes qui ne seraient pas définies dans le wp-config.php
  • Checker si WordPress est en mode maintenance ou non (pendant une mise à jour par exemple)
  • Récupérer le cache s’il existe
  • Charger quelques « classes » de WordPress
  • Charger l’internationalisation dans le CMS, fichiers de traduction du core, des extensions et des thème
  • Récupérer et exécuter les extensions indispensables (Must-Use Plugin)
  • Charger la configuration du multisite (si l’install est un multisite)
  • Exécuter les 1ers hooks
  • Créer les type de contenu et taxonomies par défaut dans WordPress
  • Récupérer les extensions et charger celles actives
  • Récupérer les thèmes installés

Chouette… ça ressemblerait presque à une chambre mal rangée. Ce qu’il faut retenir c’est que tout est là, tout est configuré, c’est prêt à être utiliser.

Ça tombe bien il n’y a pas de suite… Revenons donc dans le fichier wp-blog-header.php

Récupérer les données de la requête grâce à la fonction wp()

Une fois toutes les classes importées, les constantes définies, la base de donnée connectée il est temps d’utiliser la fonction wp(). Voici le contenu de cette méthode :

/**
 * Set up the WordPress query.
 *
 * @since 2.0.0
 *
 * @global WP       $wp           Current WordPress environment instance.
 * @global WP_Query $wp_query     WordPress Query object.
 * @global WP_Query $wp_the_query Copy of the WordPress Query object.
 *
 * @param string|array $query_vars Default WP_Query arguments.
 */
function wp( $query_vars = '' ) {
	global $wp, $wp_query, $wp_the_query;

	$wp->main( $query_vars );

	if ( ! isset( $wp_the_query ) ) {
		$wp_the_query = $wp_query;
	}
}

Alors qu’en est-il ? On voit pas mal de variables globales qui sont chargées puis utilisé. Intéressons nous à $wp dans un 1er temps. Il s’agit d’une instance de la classe WP, j’invente rien c’est la documentation qui le dit.

On peut voir que la méthode main() est exécutée.

Dans cette fonction il se passe en réalité pas mal de choses, à savoir :

  1. WordPress récupère l’utilisateur courant s’il est connecté ;
  2. Il parse la requête à partir de l’URL et essaie de la faire matcher avec un schéma d’URL qu’il connait ;
  3. Ensuite, il prépare les headers à envoyer au navigateur pour convenir si le contenu qu’on va livrer est en cache ou non ;
  4. C’est alors que le CMS construit une WP_Query à partir des informations qui ont été parsé en amont ;
  5. Si cette requête n’aboutit à rien alors WordPress renvoie un code erreur 404 ;
  6. Dans tous les autres cas, il enregistre dans des variables globales $wp_query, $query_string, $posts, $request le résultats de toutes les opérations qu’il vient de faire.

Finito ?

Et non… mais on arrive à la fin bientôt promis ! Toutes ces informations étant inutiles si elles ne sont affichées nulle part. WordPress s’occupe en dernier temps de charger le thème adéquat.

Choisir le modèle de page à afficher avec template-loader.php

Si vous êtes arrivé jusque là et que vous avez suivi les premières étapes, vous vous rappelez sans doute de la constante WP_USE_THEMES. Mais si, celle qu’on avait dans le fichier index.php, vous vous souvenez ?

Je ne vais pas vous refaire le layus dans quel cas cela peut être utile de désactiver le chargement des thèmes.

Sachez que ce n’est qu’à ce moment là dans le cycle de vie de WordPress en tout cas qu’elle est utilisée.

Très tôt dans ce fichier le hook template_redirect est lancé. Cette action peut être utile si vous souhaitez restreindre le contenu d’une page aux utilisateurs connectés par exemple.

De la même manière, certaines actions spécifiques aux robots ou au flux RSS sont lancées. Mais le plus intéressant est la suite.

$tag_templates = array(
		'is_embed'             => 'get_embed_template',
		'is_404'               => 'get_404_template',
		'is_search'            => 'get_search_template',
		'is_front_page'        => 'get_front_page_template',
		'is_home'              => 'get_home_template',
		'is_privacy_policy'    => 'get_privacy_policy_template',
		'is_post_type_archive' => 'get_post_type_archive_template',
		'is_tax'               => 'get_taxonomy_template',
		'is_attachment'        => 'get_attachment_template',
		'is_single'            => 'get_single_template',
		'is_page'              => 'get_page_template',
		'is_singular'          => 'get_singular_template',
		'is_category'          => 'get_category_template',
		'is_tag'               => 'get_tag_template',
		'is_author'            => 'get_author_template',
		'is_date'              => 'get_date_template',
		'is_archive'           => 'get_archive_template',
	);

Pour celles et ceux qui sont déjà à l’aise avec le Template Hierarchy, vous aurez reconnu les différents modèle de page que connait WordPress par défaut.

C’est à ce moment là que le CMS récupère depuis le thème actif le modèle de page qui va être servit côté front par la suite.

Un dernier hook template_include est exécutée avant l’affichage de ce dernier. Il est donc possible même au dernier moment de venir écraser l’affichage de la donnée. Certains plugins comme WooCommerce se branche à ce moment précis pour charger la vue adéquate en fonction de la ressource demandée.