ENI Service - WordPress - PHP

bg right contain

Paul Schuhmacher

Durée : 28h

Novembre 2025

Condensé (dernier jour) : ThÚme parent-enfant, optimisations, déploiement et configuration, misc

ThĂšmes enfants #

Depuis WordPress 2.7

L’extension de thĂšme s’arrĂȘte Ă  la relation parent-enfant. Pas de troisiĂšme niveau (thĂšme petit-enfant impossible)

Avantages Ă  utiliser un thĂšme enfant #

Créer un thÚme enfant #

Renseigner la directive Template: dans le fichier style.css du thĂšme enfant :

/**
 * Theme Name: Mon Theme
 * Template:   twentytwentyfour
 * ...other header fields
 */

Mon Theme étend le thÚme twentytwentyfour

Activer le thùme comme n’importe quel thùme.

Développer le thÚme enfant : charger le CSS du thÚme parent #

Si un thĂšme classique, charger le CSS du thĂšme parent avec la fonction get_parent_theme_file_uri():

add_action( 'wp_enqueue_scripts', 'mon_theme_enqueue_styles' );

function mon_theme_enqueue_styles() {
//Charger la feuille de style du thĂšme parent
 wp_enqueue_style( 
  'parent-style', 
  get_parent_theme_file_uri( 'style.css' )
 );
 //Charger la feuille de style du thĂšme enfant (override parent)
 wp_enqueue_style( 
  'mon-theme-style', 
  get_stylesheet_uri()
 );
}

Templates, parts et patterns #

Dans le thÚme enfant, créer uniquement les templates qui doivent personnaliser ceux du thÚme parent. Pour cela, il suffit de créer le template PHP correspondant dans le thÚme enfant.

Lorsque WordPress va choisir le template Ă  utiliser, il va d’abord scanner le rĂ©pertoire du thĂšme enfant. S’il y trouve le template il l’utilise, sinon il utilise celui du parent (fallback).

On peut ainsi surcharger (override) uniquement un ou plusieurs templates dans le thÚme enfant, tout en bénéficiant des templates du parent.

Le fichier functions.php #

À l’activation d’un thùme, WordPress cherche un fichier functions.php à la racine du thùme. S’il le trouve, il l’inclut automatiquement (require).

Le fichier functions.php du thÚme enfant ne remplace pas (override) celui du thÚme parent. Les deux fichiers sont chargés. Le fichier functions.php du thÚme enfant est chargé en premier, celui du thÚme parent en second.

themes/
    parent/
        functions.php    <= chargé en second
        style.css
        index.php
    enfant/
        functions.php    <= chargé en premier
        style.css
        index.php

Inclure un fichier PHP #

Pour construire les bons paths, par exemple lors de l’inclusion d’un fichier source PHP dans un template ou functions.php, utiliser la fonction get_theme_file_path() :

//Par ex, dans functions.php du thĂšme enfant
require_once get_theme_file_path( 'inc/functions-helpers.php' );

Développer des bons sites WordPress fiables et performants #

Valider le markup HTML auprĂšs du W3C #

Utiliser le service du W3C pour valider le markup de vos pages web. Un markup valide est à la base d’un rendu de pages web fiable, stable et accessible.

Un markup cassĂ© (c’est mal !) :

Suivre les recommandations de la communauté WordPress #

Consulter les recommandations sur le site officiel :

Bien utiliser WordPress 1/2 #

Bien utiliser WordPress 2/2 #

Optimisation #

Techniques d’optimisation d’applications WordPress (comme tout site/service web) : obtenir la rĂ©ponse HTTP et la ressource demandĂ©e par le client le plus rapidement possible.

Optimisation des applications web #

Sur le web, les performances ne se gagnent pas spĂ©cialement sur l’optimisation du code*, mais sur les accĂšs lecture/Ă©criture (IO) : requĂȘtes HTTP, accĂšs disques, accĂšs DRAM, accĂšs base de donnĂ©es, connexions TCP/IP, etc.

Visionnage recommandé : Performance Optimization - PHP Tour 2016, de Fabien Potencier (créateur de Symfony)

*Dans des langages haut niveau comme PHP, il y a une grande diffĂ©rence entre le code que vous Ă©crivez et le code qui est rĂ©ellement exĂ©cutĂ©, mĂȘme si cela n’empĂȘche pas d’écrire du code efficace, idiomatique et performant.

Optimiser APRÈS avoir fait des mesures (profiling et monitoring) #

Optimiser
 :

Il faut identifier les points de congestion. Inutile d’optimiser “tout”, aveuglĂ©ment.

Utiliser des outils pour monitorer/profiler :

Plugin Query Monitor #

bg right contain

Lire les statistiques :

Bien choisir sa SAPI PHP : PHP-FPM ou FrankenPHP #

Utiliser un serveur web qui supporte la SAPI PHP-FPM (Apache fast cgi, nginx) ou utiliser la nouvelle SAPI FrankenPHP (le futur).

Installer PHP-FPM (serveur Debian/Ubuntu) #

apt install php8.5-fpm php8.5-opcache

Configurer PHP-FPM (processus maĂźtre) #

Éditer le fichier /etc/php/8.5/fpm/php-fpm.conf :

# Nombre max de processus enfants qui peuvent échouer dans l'intervalle donné 
# jusqu'Ă  ce qu'on demande au processus maitre de restart (gracefully)
emergency_restart_threshold = 10
emergency_restart_interval = 1m

Ici le processus maitre redémarre si 10 processus enfants échouent sur une période de 1 minute.

Configuration de pool de processus PHP-FPM (child processes) #

Éditer le fichier (www est le pool par dĂ©faut, on peut en crĂ©er plusieurs) /etc/php/8.2/fpm/pool.d/www.conf :

#proprietaire du pool (user deploy dédié)
user=deploy
group=deploy
#ip et port sur le quel php fpm accepts inbound request
listen = 127.0.0.1:9000
#Securité : n'autoriser que la machine hote de forward vers le pool
listen.allowed_clients = 127.0.0.1
#nombre max de process enfant qui peut exister chaque instant
#a adapter en fonction de la RAM de la machine (~5M par process, 512mB/5 ~ 51)
pm.max_children = 51
#Le nombre de pools dispos immédiatement qd php-fpm démarre
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 4
#nb de requetes a traiter max par process avant d'etre libéré et recyclé 
pm.max_requests = 1000
#path vers fichier de log pour les requetes qui prennent plus de [n] seconds a process.
#utile pour identifier les bottleneck
#slowlog = /path/vers/log
#request_slowlog_timeout = /

Cache(s) #

“There are only two hard things in Computer Science: cache invalidation and naming things.” Phil Karlton (Netscape, Xerox Parc)

Spoiler : L’utilisation du cache n’est pas magique, apporte gĂ©nĂ©ralement des bons rĂ©sultats en terme de performances mais peut poser aussi des problĂšmes si mal configurĂ©. Ne remplace pas de suivre les bons principes de design et d’usage du framework. Permet d’amplifier les performances d’un bon systĂšme.

Les différentes couches de cache #

Toute les couches de caches pour WordPress #

Cache PHP : Opcache et JIT #

Configuration de la machine virtuelle de PHP (Zend Engine) via des fichiers php.ini (à privilégier) ou des directives (.htacces par ex. avec serveur Apache) :

Configuration Opcache and JIT #

;Activer l'opcache (mise en cache des opcodes, fichiers PHP compilés)
opcache.enable=1
;Taille mémoire (DRAM) alloué à l'opcache
opcache.memory_consumption=64
;Quantité de mémoire pour les 'interned string', string répétées mise en cache
opcache.interned_strings_buffer=16
; Nombre max de fichiers a stocker dans le cache opcode (> votre nombre de fichiers)
opcache.max_accelerated_files=5000
; Dev : Activé, check si cache est frais tous les revalidate_freq
; Prod : à désactiver (cache des scripts est toujours frais, a mettre à jour au déploiement !)
opcache.validate_timestamps=1
; Fréquence à laquelle valider le cache. A de l'effet uniquement si validate_timestamps est activé En dev, on revalide le cache à chaque fois
opcache.revalidate_freq=0
; Déléguer la libération de la mémoire au gestionnaire de mémoire du zend engine
opcache.fast_shutdown=1
; Utiliser le cache disque en plus du cache ram
opcache.file_cache=/var/cache/opcache
opcache.file_cache_only=0
opcache.file_cache_consistency_checks=1
opcache.enable_cli=1
; Just In Time (JIT) compilation
opcache.enable=1
opcache.enable_cli=1
opcache.jit_buffer_size=100M
opcache.jit=tracing

Proposition INI en mode développement #

display_errors = Off
log_errors = On
error_log = /var/log/wordpress.log
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT
file_uploads = On
memory_limit = 64M
post_max_size = 64M
upload_max_filesize = 64M
max_execution_time = 5
zlib.output_compression = On
zlib.output_compression_level = 1
output_buffering=4096
implicit_flush=false
realpath_cache_size=64k ;Cache des path des include (require)

opcache.enable=1
opcache.memory_consumption=64
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=5000
opcache.validate_timestamps=0
opcache.fast_shutdown=1
opcache.file_cache=/var/cache/opcache
opcache.file_cache_only=0
opcache.file_cache_consistency_checks=1
opcache.validate_timestamps=1
opcache.revalidate_freq=0
opcache.enable_cli=1

Proposition INI en mode production #

À tuner en fonction de l’application, son usage et de l’environnent

display_errors = Off
log_errors = On
error_log = /var/log/wordpress.log
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT
file_uploads = On
memory_limit = 64M
post_max_size = 64M
upload_max_filesize = 64M
max_execution_time = 60
zlib.output_compression = On
zlib.output_compression_level = 5

opcache.enable=1
opcache.memory_consumption=64
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=5000
opcache.validate_timestamps=0
opcache.fast_shutdown=1
opcache.file_cache=/var/cache/opcache
opcache.file_cache_only=0
opcache.file_cache_consistency_checks=1

; Just In Time (JIT) compilation
opcache.enable=1
opcache.enable_cli=1
opcache.jit_buffer_size=100M
opcache.jit=tracing

RĂ©initialiser l’Opcache (PHP-FPM) #

Reset le cache manuellement (au déploiement, redémarrer le pool) :

systemctl restart php8.5-fpm

Depuis un script PHP :

<?php
opcache_reset()

Cache Objet avec Redis #

Peut ĂȘtre fait avec une autre techno, comme Memcached

Installer Redis et le plugin Redis Object Cache #

Configuration de WordPress #

Dans wp-config.php :


define('WP_REDIS_HOST', 'redis');
define('WP_REDIS_PORT', 6379);
define('WP_CACHE', true);
//Autres configs importantes : (prod)
//Sécurité : créer un user redis et le renseigner ici sous la forme ['user', 'password']
//define('WP_REDIS_PASSWORD', ['user','password']);
//Fonctionne aussi avec un socket unix ('unix')
//define('WP_REDIS_SCHEME', 'tcp');
//Timeout connexion en secondes
//define('WP_REDIS_TIMEOUT', 1);
//Timeout ecriture/lecture
//define('WP_REDIS_READ_TIMEOUT', 1);
//Max TTL pour les clefs de WordPress en secondes (1h)
//define('WP_REDIS_MAXTTL', 3600);

Voir toutes les configurations

Cache redis #

w:600

Cache redis, comment le lire (stats) #

Le plugin Query Monitor permet de l’afficher !

Calcul du Hit Ratio : H=HH+M⋅100H = \frac{H}{H+M} \cdot 100

Configuration de Redis #

Via un fichier de configuration :

# Mémoire maximale : ajuster selon RAM disponible (ex : 512MB)
maxmemory 512mb

# Politique d’éviction : supprime les clĂ©s les moins utilisĂ©es
maxmemory-policy allkeys-lru

# Optionnel : durée de vie par défaut des clés expirables (TTL par défaut)
# Certaines clés WordPress n'ont pas de TTL, d'autres comme les transients ont leur TTL propre

Via la CLI, sans redémarrer Redis :

CONFIG SET maxmemory 512mb
CONFIG SET maxmemory-policy allkeys-lru

Monitoring :

redis-cli INFO stats
redis-cli INFO memory
redis-cli MONITOR

Cache Applicatif (HTTP) #

Mettre en cache les pages web et les assets (CSS, JS, fonts, icons, etc.)

HTTP permet de définir des politiques de cache via les headers (notamment Cache-Control).

Le cache HTTP peut ĂȘtre placĂ© :

Cache applicatif #

bg right contain

Aucun cache HTTP utilisé par défaut par WordPress!

Configurer cache applicatif #

La majorité des plugins de cache WordPress sont orientés serveur (pas client*) : cache pages HTML sur disque ou mémoire cÎté serveur.

*Les assets (CSS/JS/fonts) sont bien mis en cache cÎté client par contre.

Gains obtenus avec ces couches #

Ces trois couches (cache objet persisté, cache applicatif, opcache) réunies et une fois le cache chauffé :

Et on ne parle pas des gains obtenus en utilisant le pool de processus PHP de PHP-FPM !

Cache de la base de données #

Il reste encore à configurer la cache du cÎté de la base de données.

Avec Redis ou Memcached, cette optimisation sera moins critique Ă©tant donnĂ© que le cache objet va rĂ©duire le nombre de requĂȘtes SQL. Mais c’est encore une piste d’amĂ©lioration possible !

Optimiser la base de données MySQL #

Pistes : Indexs, cache base de données (query cache), thread pools, optimizing tables, compression, optimizing queries (SQL), data structures optimisations, etc.

Quelques liens utiles :

Plugins recommandés #

Bon design, optimisations, maintenance, sécurité et misc.

Plugins recommandés : Cache et performances #

Combiner les bons plugins pour activer toutes les couches de cache + optimisation des assets (CSS, JS et images)

Plugins recommandés : Sécurité #

Installer un plugin dédié à la sécurité du site (peu importe lequel : WordFence, BulletProof Security, etc.) est indispensable !

Voir une liste des meilleurs plugins de sécurité publié par WPMarmite

Plugins recommandés : ACF PRO #

What else
 Should be WordPress core
 Mais l’histoire en a dĂ©cidĂ© autrement.

Plugins recommandés : Formulaires #

Les formulaires : édition des champs, markup et intégration (HTML, CSS), navigation (plusieurs pages ?), validation, traitement et historique.

En avez-vous vraiment besoin ? Souvent
 oui, car c’est du travail (surtout s’ils sont complexes, sur plusieurs pages, avec de la validation conditionnelle nĂ©cessitant du JavaScript, etc.) mais vous pouvez aussi dĂ©velopper vos propres formulaires et leurs traitements.

Références utiles #

Consulter la bibliographie (“lectures” recommandĂ©es)