Suite à une mise à jour de PHP, le fichier d’erreurs de mon site a commencé à afficher le message suivant :
PHP Warning: Creating default object from empty value in /wp-content/themes/skyminds/functions.php on line 1213
La ligne en question ressemblait à ceci :
$posts[0]->comment_status = 'closed';Langage du code : PHP (php)
À première vue, cette ligne semble anodine. Pourtant, elle suppose plusieurs choses : que $posts existe, que $posts est un tableau, que l’index 0 existe, et que $posts[0] est bien un objet.
Si l’une de ces conditions n’est pas vraie, PHP tente parfois de créer un objet par défaut à partir d’une valeur vide. C’est ce qui déclenche l’avertissement Creating default object from empty value.
Pourquoi cette erreur apparaît
Le problème vient généralement d’une assignation de propriété sur une variable qui n’est pas un objet valide.
Exemple simple :
$post = null;
$post->comment_status = 'closed';Langage du code : PHP (php)
Ou encore :
$posts = array();
$posts[0]->comment_status = 'closed';Langage du code : PHP (php)
Dans le second cas, $posts existe bien, mais $posts[0] n’existe pas. PHP ne peut donc pas modifier la propriété comment_status d’un objet absent.
La bonne correction dépend donc du type de donnée que vous manipulez : tableau, objet générique stdClass, instance de classe, ou objet WordPress comme WP_Post.
Correction rapide : vérifier que l’objet existe
La correction la plus prudente consiste à tester l’existence du premier élément avant de modifier sa propriété :
if ( isset( $posts[0] ) && is_object( $posts[0] ) ) {
$posts[0]->comment_status = 'closed';
}Langage du code : PHP (php)
Cette version évite l’avertissement, car elle ne modifie comment_status que si $posts[0] existe et contient bien un objet.
Dans un thème WordPress, si l’on s’attend à recevoir un objet WP_Post, on peut être plus strict :
if ( isset( $posts[0] ) && $posts[0] instanceof WP_Post ) {
$posts[0]->comment_status = 'closed';
}Langage du code : PHP (php)
C’est généralement préférable, car on vérifie le type exact attendu. WordPress documente WP_Post comme la classe utilisée pour représenter les objets d’articles retournés par des fonctions comme get_post().
Ne pas initialiser au hasard avec array() ou stdClass
Dans l’ancienne version de cet article, je proposais deux pistes :
Votre score Core Web Vitals est dans le rouge ?
LCP trop lent, CLS qui saute, INP élevé — ces métriques influencent directement votre référencement et votre taux de rebond. Je sais exactement où agir dans la stack WordPress pour les corriger.
Améliorons vos Core Web Vitals →$posts = new stdClass();Langage du code : PHP (php)
ou :
$posts = array();Langage du code : PHP (php)
Ces deux lignes peuvent être correctes, mais pas dans le même contexte.
Si votre code fait ceci :
$posts[0]->comment_status = 'closed';Langage du code : PHP (php)
alors $posts doit être un tableau, et $posts[0] doit être un objet. Initialiser seulement $posts comme tableau vide ne suffit donc pas, car $posts[0] reste absent.
Si vous voulez créer manuellement cette structure, il faudrait plutôt faire :
$posts = array();
$posts[0] = new stdClass();
$posts[0]->comment_status = 'closed';Langage du code : PHP (php)
Mais dans WordPress, ce n’est généralement pas ce que vous voulez faire. Si $posts est censé contenir des articles, il vaut mieux récupérer de vrais objets WP_Post ou vérifier que la requête a bien retourné un résultat.
Cas WordPress : vérifier le résultat d’une requête
Dans WordPress, cette erreur apparaît souvent après une requête qui ne retourne aucun article.
Par exemple :
$posts = get_posts(
array(
'post_type' => 'post',
'posts_per_page' => 1,
)
);
$posts[0]->comment_status = 'closed';Langage du code : PHP (php)
Si get_posts() retourne un tableau vide, $posts[0] n’existe pas. Il faut donc vérifier le résultat avant de l’utiliser :
$posts = get_posts(
array(
'post_type' => 'post',
'posts_per_page' => 1,
)
);
if ( isset( $posts[0] ) && $posts[0] instanceof WP_Post ) {
$posts[0]->comment_status = 'closed';
}Langage du code : PHP (php)
C’est déjà mieux, mais il faut se poser une autre question : souhaitez-vous seulement modifier l’objet en mémoire, ou voulez-vous réellement fermer les commentaires dans la base de données ?
Modifier l’objet ne modifie pas forcément la base de données
La ligne suivante modifie la propriété de l’objet PHP en mémoire :
$posts[0]->comment_status = 'closed';Langage du code : PHP (php)
Mais elle ne met pas forcément à jour l’article dans la base de données.
Pour fermer réellement les commentaires d’un article WordPress, utilisez plutôt wp_update_post() :
$posts = get_posts(
array(
'post_type' => 'post',
'posts_per_page' => 1,
'fields' => 'ids',
)
);
if ( ! empty( $posts[0] ) ) {
wp_update_post(
array(
'ID' => (int) $posts[0],
'comment_status' => 'closed',
)
);
}Langage du code : PHP (php)
Cette version est plus claire : on récupère un ID, puis on demande à WordPress de mettre à jour l’article. C’est beaucoup plus propre que de modifier directement un objet retourné par une requête.
Version WPCS et PHP 8.3+
Voici une version plus propre, compatible avec PHP moderne et les standards WordPress :
<?php
/**
* Close comments for the latest post matching a query.
*
* @return void
*/
function sky_close_comments_for_latest_post(): void {
$post_ids = get_posts(
array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 1,
'fields' => 'ids',
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
)
);
if ( empty( $post_ids[0] ) ) {
return;
}
wp_update_post(
array(
'ID' => (int) $post_ids[0],
'comment_status' => 'closed',
)
);
}Langage du code : HTML, XML (xml)
Ici, on évite de manipuler directement $posts[0]->comment_status. On demande à WordPress de faire la mise à jour correctement.
Les options no_found_rows, update_post_meta_cache et update_post_term_cache évitent du travail inutile si l’on ne veut récupérer qu’un ID. C’est plus léger et plus explicite.
Cas général PHP : objet ou tableau ?
Hors WordPress, la règle reste la même : il faut savoir si l’on manipule un objet ou un tableau.
Si vous voulez un objet générique :
$post = new stdClass();
$post->comment_status = 'closed';Langage du code : PHP (php)
stdClass est la classe générique vide de PHP. Elle accepte les propriétés dynamiques, contrairement aux classes modernes qui peuvent déclencher des avertissements en PHP 8.2+ si l’on ajoute des propriétés non déclarées. PHP documente d’ailleurs que stdClass est exempté de la dépréciation des propriétés dynamiques.
Si vous voulez un tableau associatif :
$post = array();
$post['comment_status'] = 'closed';Langage du code : PHP (php)
Mais il ne faut pas mélanger les deux syntaxes :
// Objet.
$post->comment_status = 'closed';
// Tableau.
$post['comment_status'] = 'closed';Langage du code : PHP (php)
Si vous utilisez la flèche ->, vous travaillez avec un objet. Si vous utilisez les crochets [], vous travaillez avec un tableau.
PHP 8.2 et les propriétés dynamiques
Depuis PHP 8.2, la création de propriétés dynamiques sur une classe qui ne les déclare pas est dépréciée, sauf exceptions. PHP indique que cette dépréciation peut être corrigée en déclarant la propriété, en utilisant l’attribut #[AllowDynamicProperties], ou en s’appuyant sur des méthodes magiques comme __get() et __set().
Exemple problématique :
class Post_Data {
}
$post = new Post_Data();
$post->comment_status = 'closed';Langage du code : PHP (php)
En PHP 8.2+, ce code peut déclencher :
Deprecated: Creation of dynamic property Post_Data::$comment_status is deprecatedLangage du code : PHP (php)
La bonne correction consiste à déclarer la propriété :
class Post_Data {
public string $comment_status = 'open';
}
$post = new Post_Data();
$post->comment_status = 'closed';Langage du code : PHP (php)
Ou à utiliser un tableau si le modèle de données est réellement dynamique :
$post_data = array(
'comment_status' => 'closed',
);Langage du code : PHP (php)
Donc, aujourd’hui, je déconseille de corriger ce type d’erreur en créant des propriétés à la volée sur n’importe quel objet. Cela peut fonctionner en PHP 7, puis se transformer en avertissement en PHP 8.2, et probablement en problème plus sérieux à terme.
Erreur liée à E_STRICT : nuance importante
Dans l’ancienne explication, j’évoquais E_STRICT. C’était vrai dans le contexte des anciennes versions de PHP, mais la situation a changé.
Depuis PHP 8.0, la valeur par défaut de error_reporting est E_ALL, alors qu’avant PHP 8.0 la configuration recommandée pour la production excluait notamment E_DEPRECATED et E_STRICT. La documentation PHP indique également que la valeur par défaut de error_reporting est désormais E_ALL.
En pratique, une mise à jour de PHP peut donc faire apparaître des avertissements ou dépréciations qui existaient déjà dans le code, mais qui n’étaient pas visibles auparavant.
La solution n’est pas de masquer les erreurs, mais de corriger les types et les structures de données. C’est moins agréable sur le moment, mais bien meilleur pour la santé du code.
Ne pas masquer l’erreur avec @
On pourrait être tenté d’écrire ceci :
@$posts[0]->comment_status = 'closed';Langage du code : PHP (php)
À éviter. L’opérateur @ masque l’erreur, mais il ne corrige pas le problème. Vous aurez toujours une variable dans un état inattendu, simplement avec moins de bruit dans les logs.
En développement, les logs sont là pour signaler un problème réel. Les faire taire revient à mettre du scotch sur un voyant rouge. Très décoratif, rarement mécanique.
Comment diagnostiquer rapidement
Avant de corriger, inspectez le type réel de la variable :
var_dump( $posts );Langage du code : PHP (php)
Dans WordPress, évitez d’afficher cela en production. Préférez le log :
error_log( print_r( $posts, true ) );Langage du code : PHP (php)
Ou une vérification plus ciblée :
error_log( gettype( $posts ) );
if ( isset( $posts[0] ) ) {
error_log( gettype( $posts[0] ) );
}Langage du code : PHP (php)
Vous saurez alors si vous manipulez un tableau vide, un objet, un tableau d’objets, ou une valeur inattendue.
Mémo rapide
// Problème courant.
$posts[0]->comment_status = 'closed';
// Correction minimale.
if ( isset( $posts[0] ) && is_object( $posts[0] ) ) {
$posts[0]->comment_status = 'closed';
}
// Correction WordPress plus stricte.
if ( isset( $posts[0] ) && $posts[0] instanceof WP_Post ) {
$posts[0]->comment_status = 'closed';
}
// Si l’on veut vraiment créer un tableau contenant un objet.
$posts = array();
$posts[0] = new stdClass();
$posts[0]->comment_status = 'closed';
// Si l’on veut un tableau associatif.
$post = array();
$post['comment_status'] = 'closed';
// Si l’on veut modifier réellement un article WordPress.
wp_update_post(
array(
'ID' => 123,
'comment_status' => 'closed',
)
);Langage du code : PHP (php)
Conclusion
L’erreur Creating default object from empty value apparaît lorsque PHP tente d’assigner une propriété à une valeur qui n’est pas un objet valide.
Dans l’exemple suivant :
$posts[0]->comment_status = 'closed';Langage du code : PHP (php)
il faut vérifier que $posts est bien un tableau, que $posts[0] existe, et que $posts[0] est bien un objet.
Dans WordPress, si l’objectif est de fermer les commentaires d’un article, la meilleure solution consiste souvent à utiliser wp_update_post() plutôt que de modifier directement une propriété d’objet.
Le bon réflexe est donc simple : ne corrigez pas l’erreur en initialisant une variable au hasard. Vérifiez le type attendu, testez l’existence de la donnée, puis utilisez l’API adaptée. PHP râle, certes, mais cette fois il a plutôt raison.
Votre base de données ralentit tout ?
Tables wp_options surchargées, autoload incontrôlé, requêtes non indexées — une base WordPress mal entretenue finit toujours par plomber les temps de réponse. Je l'audite, je la nettoie, je l'optimise.
Diagnostiquons votre base de données →



Je viens d’avoir cette erreur en passant en prod un site sous codeigniter (aucun warning en dev) et aucune des 2 solutions ne passe malheureusement.
Est ce que depuis tu aurais trouvé une autre solution supplémentaire?
Merci