Paul Schuhmacher
Durée : 28h
Novembre 2025
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)
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èmetwentytwentyfour
Activer le thème comme n’importe quel thème.
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()
);
}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.
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.phpPour 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' );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 !) :
Consulter les recommandations sur le site officiel :
WP_Query ou
get_posts, pas
query_posts;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.
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… :
Il faut identifier les points de congestion. Inutile d’optimiser “tout”, aveuglément.
Utiliser des outils pour monitorer/profiler :
Lire les statistiques :
memory_get_peak_usage) (~ 5-20 MB);Utiliser un serveur web qui supporte la SAPI PHP-FPM (Apache fast cgi, nginx) ou utiliser la nouvelle SAPI FrankenPHP (le futur).
apt install php8.5-fpm php8.5-opcacheÉ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 = 1mIci le processus maitre redémarre si 10 processus enfants échouent sur une période de 1 minute.
É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 = /“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.
Cache-Control,
ETag, Last-Modified). Permet de mettre en
cache les pages web côté client. Fonctionnalité
fondamentale et centrale du protocole, implémenté dès HTTP 1.1
(a sauvé le web, menacé par son propre succès !) ;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) :
;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=tracingdisplay_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À 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=tracingReset le cache manuellement (au déploiement, redémarrer le pool) :
systemctl restart php8.5-fpmDepuis un script PHP :
<?php
opcache_reset()Peut être fait avec une autre techno, comme Memcached
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);Le plugin Query Monitor permet de l’afficher !
maxmemory). En rajouter si trop de
miss.Calcul du Hit Ratio :
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 propreVia la CLI, sans redémarrer Redis :
CONFIG SET maxmemory 512mb
CONFIG SET maxmemory-policy allkeys-lruMonitoring :
redis-cli INFO stats
redis-cli INFO memory
redis-cli MONITORMettre 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é :
Aucun cache HTTP utilisé par défaut par WordPress!
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.
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 !
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 !
Pistes : Indexs, cache base de données (query cache), thread pools, optimizing tables, compression, optimizing queries (SQL), data structures optimisations, etc.
Quelques liens utiles :
Bon design, optimisations, maintenance, sécurité et misc.
Combiner les bons plugins pour activer toutes les couches de cache + optimisation des assets (CSS, JS et images)
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
What else… Should be WordPress core… Mais l’histoire en a décidé autrement.
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.