Accueil > WordPress > Optimisation technique de WordPress > Transient et WordPress : comment les utiliser ?

Transient et WordPress : comment les utiliser ?

Publié le 14 février 2013 Optimisation technique de WordPress

Pour ceux qui ont suivi mes derniers articles, j'étais conférencier lors du dernier WordCamp Paris. Lors des ateliers du samedi, nous avons discuté des solutions de mise en cache des données sur WordPress, et notamment des transients. Cette fonctionnalité est relativement puissante, mais il s'avère que je ne les utilisais pas forcément à bon escient, tout comme vous d'ailleurs...

Tête dans le sable
Le meilleur système de cache du monde : le transient sablé...

Qu'est ce qu'un transient ?

Sous ce terme barbare se cache une fonctionnalité intéressante de WordPress qui permet de mettre en cache temporairement une information, et cela directement en base de données. Elle permet notamment d'éviter de recalculer certains éléments récurrents de vos pages, vous permettant ainsi d’accélérer le temps de chargement. Cela peut être par exemple :

  • la liste des articles les plus commentés
  • le contenu de votre blogroll
  • vos derniers tweets
  • ...

Le transient se stocke en base de données dans la table options. Libre à vous de créer ou de récupérer la valeur d'un transient pour l'utiliser, que ce soit dans un thème ou un de vos plugin.

Cela fonctionne comment ?

Le concept

Vous pouvez mettre ce que vous voulez dans un transient. Cela peut se résumer à un chiffre ou à un mot tout comme à un long contenu html. Voici comment en créer un :

set_transient( $nom, $valeur, $expiration );
  • $nom est le nom unique du transient (45 caractères maximum).
  • $valeur est le contenu de celui-ci.
  • $expiration est la durée en secondes au bout de laquelle le transient n'est plus valide (mais existe toujours en base de données).

Pour récupérer la valeur d'un transient dans WordPress, il faut alors utiliser la fonction suivante :

get_transient($nom);

Pour tester proprement si un transient existe et s'il est toujours valide, utiliser le code ci-dessous. La partie du code XX ne s’exécutera que si le transient n'existe pas ou s'il est expiré :

if ( false === ( $valeur = get_transient($nom) ) ) {
     // XXX
}

Un exemple pratique

Maintenant que l'on connait les fonctions de base, voici un exemple pratique.

Imaginons que vous ayez une fonction toto() qui récupère les 5 derniers commentaires de votre site et que vous voulez afficher cette liste sur toutes les pages. Vous pourriez utiliser la fonction suivante dans le fichier functions.php de votre thème WordPress :

function seomix_transient(){   
 // Quel est le nom du transient
 $nomtransient = 'tototransient';

 // Le transient est-il inexistant ou expiré ?
 if ( false === ( $transient = get_transient( $nomtransient ) ) ) {

  // Si oui, je fais appelle à n'importe quelle fonction pour donner une valeur au futur transient.
  // Dans mon exemple, ce sera ma fonction toto.
  $value = toto();

  // Je met à jour la valeur du transient avec $value, et j'indique à WordPress une durée d'expiration de 60 secondes
  set_transient($nomtransient, $value, 60);

  // Je met à jour la valeur de ma variable $transient
  $transient = get_transient( $nomtransient );
 }

 //Nous renvoyons la valeur du transient mis à jour
 return $transient; 
}

Ensuite, il suffira d'utiliser le code suivant dans votre thème à l'endroit désiré :

<?php echo seomix_transient(); ?>

Le concept est simple :

  • Au premier chargement d'une page contenant cette fonction, WordPress va vérifier si le transient existe.
    • S'il n'existe pas, il va lui donner la bonne valeur puis l'afficher.
    • S'il existe, il va directement afficher la bonne valeur
  • Dans les quelques secondes qui suivent, si une nouvelle page est chargée avec cette fonction à l'intérieur, WordPress va vérifier son existence puis afficher sa valeur sans la recalculer.
  • Si plus de 60 secondes se sont écoulées, le transient sera vérifié, recalculé, mis à jour puis affiché.

La fonction donnée en exemple ne sera calculée que toutes les 60 secondes maximum, peu importe le  nombre de pages et de visiteurs de votre site Internet pendant cette durée. Sur des fonctions très simples, le gain sera faible car WordPress doit toujours faire au moins deux requête pour vérifier si le transient existe. En d'autres termes :

  • plus le contenu du transient est complexe à générer, plus le gain de performance sera élevé pour votre site (car les ressources allouées pour vérifier l'existence du transient seront "amorties").
  • plus un même transient est présent sur vos différentes pages, plus le gain sera là aussi élevé (un seul calcul nécessaire pour plusieurs pages).

WordPress MU

Si vous gérez un WordPress Multisite, sachez que vous pouvez également utiliser les fonctions transversales ci-dessous pour cacher la même donnée sur tous les sites en même temps. Elles fonctionnent exactement de la même manière que les transients basiques :

set_site_transient()
get_site_transient()

Quand utiliser un transient ?

Nous venons de comprendre le concept de base. Maintenant, posons-nous la seule et bonne question à se poser :

Dois-je utiliser les transients de WordPress ?

La réponse est oui et non, car tout dépendra de ce que vous voulez faire avec. Tout d'abord, je vais partir du fait que vous avez un autre système de cache déjà mis en place. Et celui-ci peut-être de deux types :

  • Si celui-ci est géré du côté serveur, les transients seront très peu utiles. Par exemple, si vous avez installé correctement Nginx, Varnish ou encore MemCached, tous les autres système de mise en cache n'apporteront pas grand chose à vos visiteurs puisque le contenu aura déjà été mis en cache par votre serveur (je simplifie mais c'est l'idée de base).
  • Si le cache est généré par l'utilisateur, par exemple avec des plugins comme WP-Super Cache ou W3 Total Cache, les transients seront plus utiles.
Cache serveur
Le cache serveur, il n'y a que ça de vrai...

Quel que soit le système de cache de votre site, les transients ne peuvent les remplacer. Ils viendront le compléter.  Il existe en réalité deux cas de figure où il est fortement conseillé de les utiliser :

  • un même contenu est présent sur plusieurs pages (derniers commentaires, une sélection d'articles, une blogoliste, une galerie d'image, ...). On limite ainsi le calcul d'une donnée identique.
  • vous utilisez du contenu issu d'un site externe. Vous limitez ainsi les requêtes DNS et la consommation de bande passante et d'API (celle de Twitter, de Facebook, ...).

Pour le dernier point, c'est là où les transients seront vraiment efficaces. Dans le cas où vous faites appel à des données externes comme par exemple Twitter, les transients vont vraiment apporter un gain de performance en évitant de nombreuses requêtes superflues. Par exemple, le transient peut stocker pendant 10 minutes les derniers tweets. Ainsi, votre site Internet ne fera que 6 requêtes maximum par heure aux serveurs de Twitter, tout en laissant votre site dynamique et réactif.

Bien utiliser les transients de WordPress

Je connaissais déjà les points que j'ai cité juste avant, mais c'est au WordCamp Paris que j'ai réalisé deux choses :

  • Un transient ne doit pas avoir obligatoirement un délai d'expiration.
  • Un transient expiré reste en base de données.

Commencez donc pas ne pas mettre du délai d'expiration si vous savez que la donnée calculée ne changera plus jamais.

L'autre cas de figure est de se demander à partir de quand vous n'utiliserez plus un transient. Si vous en avez créé un et que vous ne l'utilisez plus, celui-ci restera dans votre base de données inutilement. En effet, WordPress ne le supprimera que si vous essayez d'y accéder. En fonction de nombre de plugins installés puis désinstallés, ou du changement de vos thèmes, il est possible que vous ayez des dizaines de transients inutiles dans la table option de WordPress. Il est donc nécessaire de faire un peu le ménage. Pour vous donner un ordre d'idée, j'ai supprimé 1,4Mo de données inutiles après avoir appliquer l'astuce qui va suivre.

Le code initial est tiré du très bon plugin "Artiss Transient Cleaner", et a été ensuite optimisé par mes soins. Le plugin est excellent mais il supprime tous les transients (ceux expirés et ceux qui ne le sont pas) lors de la mise à jour de la base de données WordPress. Comme je ne juge pas cela pertinent comme comportement par défaut, le code a été simplifié.

Tout d'abord, il faut définir la durée au bout de laquelle les différentes corbeilles de WordPress vont se vider (articles, commentaires, ...). Le code et le plugin se greffent en effet sur cette fonction pour supprimer tous les transients expirés. Cela se définit avec la ligne suivante à placer dans le fichier wp-config.php situé à la racine de votre site :

define('EMPTY_TRASH_DAYS', 3 );

Dans la ligne, définissez la durée en jours (ici 3) au bout de laquelle WordPress doit faire le ménage. Ensuite, copiez/collez le code suivant dans le fichier functions.php de votre thème :

// Création de l'action qui va déclencher la suppression des transients    
function seomix_content_transients_opti() {
 seomix_action_delete_transient();}

// Activation de l'action en m%C3%AAme temps que wp_scheduled_delete
//La variable EMPTY_TRASH_DAYS doit %C3%AAtre définie dans le fichier WP-Config
//exemple : define('EMPTY_TRASH_DAYS', 3 );
add_action( 'wp_scheduled_delete', 'seomix_content_transients_opti' );

// Fonction de suppression des transients  
function seomix_action_delete_transient() {
 // Si WordPress ne fait pas appel à un cache externe
 global $_wp_using_ext_object_cache;
 if ( !$_wp_using_ext_object_cache ) {
  //On récupère la globale du site
         global $wpdb;
         // On récupère l'heure actuelle
         $time = time();
         // On récupère tous les transients
         $sql = "SELECT option_name FROM $wpdb->options WHERE option_name LIKE '_transient_timeout%25' AND option_value < $time";
         // On les récupère proprement
         $mestransients = $wpdb->get_col( $sql );
         // Pour chacun d'entre eux, on les supprime
         foreach( $mestransients as $transient ) {
            $deletion = delete_transient( str_replace( '_transient_timeout_', '', $transient ) );
         }
         // On optimise la base de données après les suppressions
         $wpdb->query('OPTIMIZE TABLE ' . $wpdb->options);
       }
}

Vous pouvez également forcer la suppression immédiate des transient inutiles en remplaçant wp_scheduled_delete par init. Attention cependant, le code s'exécutera alors à chaque chargement de page de votre site : vous ne devez donc laisser init que le temps de recharger une de vos pages pour nettoyer les transients actuels, puis remettre la valeur wp_scheduled_delete à la place.

Et vous, comment utilisez-vous les transients ?

Daniel Roch

Expert SEO WordPress - Créateur de SeoMix et SEOKEY - Auteur de nombreux livres et conférencier

10 Commentaires

Jguiss Le 14 février 2013 à 9h44

Tu viens de me faire découvrir quelquechose ! Je suis pas très fort en mise ne cache (il n'y a qu'a voir le temps de chargement de mon site) et je pense que ces "Transient" vont peut être me permettre de gagner quelques millisecondes :) Par contre pour l'instant je ne vois pas d'autres utilisation possible uniquement les widgets de la sidebar... Faut que je revienne vite sur ton blog car je vois qu'il y pas mal d'autres articles sur l'optimisation de la vitesse :)

Julio Potier (BoiteAWeb.fr) Le 14 février 2013 à 10h47

Hello

Bien expliqué, un jour je ferais le mien aussi x) Sinon je rappelle qu'un transient avec expiration coute 2 requêtes (sauf utilisation d'un cache mémoire). Donc si vous avez 1 transient pour le last tweet, un transient pour la blogroll, un transient pour des pubs, un transient pour un RSS distant, le tout avec expiration pour faire un refresh automatique, cela vous coutera 8 requêtes de plus par page qui affiche ça. Certes, les requêtes sont légères, et il ne faut pas utiliser de cache pour subir ça.

Aussi, pourquoi un transient reste en base, car il n'est supprimé que si on fait une demande d'expiration du transient, donc un get_transient. Mais la plupart du temps on fait ça pour de nouveau l'ajouter. Une fois l'astuce/plugin supprimé, personne ne viendra faire cette demande de ce transient précis.

J'ai regardé le code pour supprimer c'est à ne pas mettre sur INIT, jamais de la vie ! Supprimer un transient avec delete_transient pour des transients avec expiration coute 2 requêtes par transient aussi ! oO

Sinon en français c'est "donnée transitoire". Voilà merci bien ;)

Daniel Roch Le 15 février 2013 à 11h08

@Julio : quand je dit de le mettre sur l'init, c'est uniquement temporairement pour forcer une suppression immédiate: le mieux reste de le laisser tel qu'indiqué dans le code pour nettoyer les transients avec la durée indiquée dans le fichier de configuration de WordPress.

Et j'ai corrigé l'article pour indiquer qu'un transient génère bien deux requêtes et non une.

Julien Maury Le 15 février 2013 à 15h10

WordPress MU? :)
Pour les transients :
J'ai proposé un article similaire sur mon blog. Même si cela se devine il faudrait préciser que les transient ne doivent pas être affectés à des données critiques pour le thème vu qu'elles ne sont pas censées être périssables.

Une chose que je n'ai pas bien saisie: la fonction que tu proposes gère donc un nettoyage automatique?
C'est une bonne idée car c'est vrai que les tables sont pleines de transients inutiles qu'il vaut mieux supprimer :)

Amaury Le 19 février 2013 à 19h21

Des choses en vrac à savoir :

1. en cas de présence du cache objet, les transients ne sont plus utilisés au profit du dit cache-objet

2. Les transients sont avant tout là pour faire du cache ponctuellement, tout en ayant la certitude, quelque soit l'environnement mutualisé, de fonctionner car aucune dépendance serveur

3. Etant donné le coté non propre de la chose, il ne faut jamais utiliser les transients en mode cache objet au sein de fonction, et utiliser de façon générique, type construction du slug du transient à la volée…

Enfin, généralement, c'est pratique pour les requêtes vers les services tiers, facebook, twitter, etc. Ca évite d'atteindre les limitations des API.

Arnaud Le 25 février 2013 à 9h30

Bonjour Daniel,

Merci, je ne connaissais pas trop non plus le rôle de ces transient, en tout cas c'est déjà plus clair.
Et de quoi optimiser encore mon site sur WordPress :)

Yannick@Journaliste rédacteur web Le 27 février 2013 à 22h33

Je tombe sur ce billet intéressant bien que super technique pour mon niveau, alors que je viens justement de faire une refonte de mon site et d'installer le plugin W3 Total Cache. En le paramétrant, je suis passé de 72 à 88 pour-cent au calcul Page Speed Grade de GTMetrix. Y a du progrès, mais avec l'aide des explications données ici, j'ai de quoi essayer d’accélérer encore un peu la chose. Merci, donc!

Olivier C Le 01 avril 2013 à 10h46

Je me pose une question : à partir du moment où l'on utilise un système de cache global pour les pages du site, le stockage par transcients a-t-il encore son utilité ?

Sinon, une petite requête SQL pour effacer tous les transcients d'une base de donnée (préfixée en "wp_") :

-- effacement de toutes les valeurs temporaires
DELETE FROM wp_options WHERE option_name LIKE '%transient%';
Amaury Le 02 avril 2013 à 10h26

Olivier -> si le cache global est utilisé avec un système tiers (APC, Memcached, Xcache) ou autre, les transients sont stockés via le cache objet, donc plus de ligne dans la table des options !

anon Le 13 juin 2014 à 11h25

Bonjour, le truk avec transient est que cela charge le server sql ce que les petit site mutualisés ne souhaite absolument pas il veulent simplement le moins de requêtes en bdd, alors la finte est d'utiliser un plugin qui met en cache les requêtes comme db cache reloaded fix

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *