Prévenir les erreurs fatales sur WordPress


""

Découvrez les meilleures pratiques de développement WordPress et consultez des exemples de code.

Des erreurs fatales peuvent faire tomber un site entier, il est donc important d’être minutieux lors du développement d’un site WordPress sur n’importe quelle plate-forme. Examinons quelques exemples qui peuvent entraîner des pannes indésirables et comment les éviter.

Erreurs fatales : fonctions en collision

Une fonction peut exister dans PHP, le noyau WordPress, un plugin ou un thème. Mais si vous déclarez une fonction qui existe déjà, PHP lancera une erreur fatale.

Par exemple, la fonction ci-dessous existe déjà dans WordPress et une erreur sera renvoyée lors de sa déclaration :

// this will cause a fatal
function get_permalink( $url ) {
    // do something
}

La meilleure façon de se protéger contre les collisions est d’envelopper leur déclaration avec `function_exists`.

Alternativement, vous pouvez utiliser :

  • Une méthode de classe
  • Un espace de noms (cela tend à introduire de la complexité)

Erreurs fatales : fonctions qui n’existent pas

PHP génère également une erreur fatale si vous essayez d’accéder à une fonction qui n’a pas été déclarée, par exemple, lorsque la fonction est déclarée dans un plugin mais que le plugin n’est pas installé ou actif.

// this will cause a fatal if Safe Redirect Manager is not active
$redirect = srm_create_redirect( '/old/', '/new/', 301);

Il est important de vérifier cela lors de la création d’un plugin qui s’appuie sur un autre plugin. Parce que WordPress ne charge pas certains fichiers wp-admin pour le front-end, il vaut la peine de vérifier cette fonction et de charger manuellement le ou les fichiers si nécessaire.

Cela peut également se produire lorsque la déclaration contient une faute de frappe ou en n’utilisant pas de préfixe d’espace de noms si nécessaire. Ces problèmes sont difficiles à éviter, alors «test de fumée” est toujours utile.

Avertissements : ne vérifie pas les valeurs de retour

Utilisation de `WP_DEBUG` dans le développement et afficher des avertissements et des avis est une bonne pratique de développement. Ces conditions d’avertissement doivent être immédiatement évidentes et peuvent être rapidement traitées et corrigées.

Les avertissements et avis PHP ne nuiront pas nécessairement à un site, mais leur présence suggère qu’il y a quelque chose qui mérite votre attention. L’élimination de tous les avertissements et avis est une bonne pratique et permet de repérer facilement les nouveaux problèmes dans le `error_log` PHP.

Remarque : Laisser trop d’avertissements inutiles ou sans réponse obstruera vos journaux, utilisera de l’espace disque et rendra difficile la recherche et la résolution de nouveaux problèmes.

Voici des avertissements ou des avis courants, ainsi qu’un exemple de code qui les provoque.

Accéder à un tableau sans s’assurer qu’il s’agit bien d’un tableau

// expecting an array
$stuff = getStuff( $args );
// unless getStuff is guaranteed to always return an array, this is not good...
foreach ( $stuff as $thing ) { // Invalid argument supplied for foreach()
    // actions
}
// this is common and also not good without checking $stuff:
$thing1 = $stuff(0);
// even worse
$thing_name = $stuff(0)->getName();

Utiliser tout ce qui n’est pas un scalaire comme index

$redirect_to = ( 'foo' => 'foo.com', 'bar' => 'bar.com' );
$c = get_categories(); // returns an array

// (other code that fails to convert $c to a single string)

// this will fail because $c is an array
$redirect_url = $redirect_to( $c );

Accéder à des objets qui ne correspondent peut-être pas à ce qui était attendu

// expecting an object
$something = getSomething( $id );
// if $something is null, this is not going to work
$something->doIt();
Certain functions return WP_Error when they fail. It's important to check that condition.
$categories = get_the_terms( $post->ID, 'category' );
// if the result is WP_Error, this next line will throw warnings
foreach ( $categories as $category ) {
    $cats() = $category->name;
}

Éviter post__not_in

L’argument `WP_Query` `post__not_in` peut sembler une option utile, mais elle peut entraîner de mauvaises performances sur un site occupé et/ou volumineux en affectant le taux de réussite du cache.

L’argument `post__not_in` est généralement utilisé pour exclure des ID de publication spécifiques des résultats d’une requête. Par exemple, si un widget affiche les cinq publications les plus récentes sur chaque page, le concepteur de votre site peut vouloir éviter d’afficher la publication actuelle dans ce widget. Cela dit, cet argument est un peu redondant, car le lecteur lit déjà ce message récent.

Comment c’est utilisé

Vous pourriez avoir un widget comme celui-ci :

// Display the most recent news posts
function my_recent_news_widget( ) {
	$args = array(
		'category_name' => 'news',
		'posts_per_page' => 5,
		'post_status' => 'publish',
		'ignore_sticky_posts' => true,
		'no_found_rows' => true,
	);
	$recent_posts = new WP_Query( $args );

	echo '<div class="most-recent-news"><h1>News</h1>';
	while ( $recent_posts->have_posts() ) {
		$recent_posts->the_post();
		the_title( '<h2><a href="' . get_permalink() . '">', '</a></h2>');
	}
	echo '</div>';
	wp_reset_postdata();
}

L’approche typique consiste à modifier cette fonction seule, en ajoutant un argument de fonction facultatif et un argument de requête `post__not_in` à la ligne 9, comme suit :

// Display the most recent news posts (but not the current one)
function my_recent_news_widget( $exclude = array() ) {
	$args = array(
		'category_name' => 'news',
		'posts_per_page' => 5,
		'post_status' => 'publish',
		'ignore_sticky_posts' => true,
		'no_found_rows' => true,
		'post__not_in' => $exclude,
	);
	$recent_posts = new WP_Query( $args );

	echo '<div class="most-recent-news"><h1>News</h1>';
	while ( $recent_posts->have_posts() ) {
		$recent_posts->the_post();
		the_title( '<h2><a href="' . get_permalink() . '">', '</a></h2>');
	}
	echo '</div>';
	wp_reset_postdata();
}

Vous l’appelleriez probablement dans un modèle avec `my_recent_news_widget( ( get_the_ID() ) );` et il afficherait les cinq messages d’actualité les plus récents, mais pas le message actuel.

Bien que l’utilisation ci-dessus soit simple, elle n’est pas idéale.

Problèmes avec cette approche

La requête, qui utilisait auparavant le cache de requêtes intégré, est désormais unique pour chaque publication ou page en raison de l’ajout de `AND ID not in ( ‘12345’ )`. C’est parce que la clé de cache (qui est un hachage des arguments) inclut désormais une liste d’au moins un ID, qui est différente pour tous les messages. Au lieu que les pages suivantes obtiennent la liste des cinq messages du cache d’objets, le cache manquera et la base de données effectuera le même travail sur plusieurs pages.

Par conséquent, chacune de ces requêtes est désormais mise en cache séparément, ce qui augmente inutilement l’utilisation de Memcached. Pour un site avec des centaines de milliers de messages, cela aura potentiellement un impact sur la taille du cache d’objets et entraînera des évictions prématurées du cache.

Que faire à la place

Dans presque tous les cas, vous pouvez améliorer considérablement la vitesse en demandant plus de messages et en sautant les messages exclus en PHP.

Améliorez les performances en vous assurant que la requête de publication est cohérente sur toutes les URL, en récupérant les six publications les plus récentes, de sorte que les publications apparaissent à partir du cache d’objets. Si vous prévoyez que la liste `$exclude` sera plus grande qu’un message, fixez la limite plus haut, peut-être à 10. Faites-en un nombre fixe, pas une variable, pour réduire le nombre de variantes de cache.

La fonction mise à jour n’exclut plus le(s) post(s) en SQL, elle utilise des conditions dans la boucle :

// Display the most recent news posts (but not the current one)
function my_recent_news_widget( $exclude = array() ) {
	$args = array(
		'category_name' => 'news',
		'posts_per_page' => 10,
		'post_status' => 'publish',
		'ignore_sticky_posts' => true,
		'no_found_rows' => true,
	);
	$recent_posts = new WP_Query( $args );

	echo '<div class="most-recent-news"><h1>News</h1>';
	$posts = 0; // count the posts displayed, up to 5
	while ( $recent_posts->have_posts() && $posts < 5 ) {
		$recent_posts->the_post();
		$current = get_the_ID();
		if ( ! in_array( $current, $exclude ) ) {
			$posts++;
			the_title( '<h2><a href="' . get_permalink() . '">', '</a></h2>');
		}
	}
	echo '</div>';
	wp_reset_postdata();
}

Tout en nécessitant un peu de logique en PHP, cette approche exploite mieux le cache des requêtes et évite de créer des variations de cache qui pourraient avoir un impact sur le site. évolutivité et stabilité.

En savoir plus sur les bonnes pratiques WordPress

Pour encore plus de conseils techniques sur le développement pour WordPress et WordPress VIP, consulter notre documentation.



<Voir les plus beaux thèmes