Combien d’articles sont actuellement en attente de relecture sur ce site ? Cette question, posée par un rédacteur en chef pressé, pousse parfois un développeur vers une requête SQL directe sur la table wp_posts, alors qu’une fonction native de WordPress répond déjà exactement à ce besoin.
wp_count_posts() renvoie un objet contenant, pour un type de contenu donné, le nombre d’éléments dans chacun des statuts de publication existants : publiés, brouillons, en attente, programmés, et tout statut personnalisé déclaré sur le site.
Utiliser wp_count_posts() au quotidien
L’appel le plus simple ne prend qu’un argument optionnel, le type de contenu concerné, avec post comme valeur par défaut :
$compteurs = wp_count_posts( 'article' );
echo 'Publiés : ' . (int) $compteurs->publish . "\n";
echo 'Brouillons : ' . (int) $compteurs->draft . "\n";
echo 'En attente : ' . (int) $compteurs->pending . "\n";
L’objet renvoyé expose une propriété par statut existant sur le site, chacune contenant le nombre correspondant. Un statut qui ne compte aucun contenu apparaît tout de même dans l’objet, avec une valeur à zéro, ce qui évite d’avoir à tester son existence avant de le lire.
Ce que la fonction fait en coulisses

En interne, wp_count_posts() exécute une requête SQL groupée par statut sur la table wp_posts, filtrée sur le type de contenu demandé, puis met le résultat en cache via l’API d’objets cache de WordPress. Cette mise en cache change tout sur un site à fort trafic administratif : un tableau de bord qui affiche ces compteurs sur chaque chargement de page ne relance pas la requête SQL à chaque fois, contrairement à une requête personnalisée écrite sans précaution.
function widget_dashboard_statuts() {
$statuts = wp_count_posts( 'article' );
printf(
'<p>%d publiés, %d en attente, %d brouillons</p>',
(int) $statuts->publish,
(int) $statuts->pending,
(int) $statuts->draft
);
}
add_action( 'wp_dashboard_setup', function () {
wp_add_dashboard_widget(
'statuts_articles',
'Statuts des articles',
'widget_dashboard_statuts'
);
} );
Le filtre à connaître pour les statuts personnalisés
Sur un site qui déclare ses propres statuts éditoriaux via register_post_status(), ces statuts apparaissent automatiquement dans le résultat de wp_count_posts(), sans configuration supplémentaire. En revanche, un filtre dédié, wp_count_posts, permet d’ajuster le résultat après coup, par exemple pour exclure un statut interne d’un affichage destiné à un public non technique :
add_filter( 'wp_count_posts', function ( $compteurs, $type, $perm ) {
unset( $compteurs->statut_technique_interne );
return $compteurs;
}, 10, 3 );
Ce que wp_count_posts() ne couvre pas
- Elle ne filtre pas par taxonomie ni par auteur : pour ce genre de croisement, une requête via
WP_Queryavec'fields' => 'ids'reste plus adaptée. - Elle ne compte pas les taxonomies : pour un total de termes par taxonomie, c’est
wp_count_terms()qu’il faut utiliser, une fonction distincte au rôle voisin mais séparé. - Le paramètre
$perm, second argument optionnel, permet de restreindre le comptage aux contenus que l’utilisateur courant a le droit de lire, utile sur une interface où tous les rôles n’ont pas la même visibilité.
Un exemple avec le paramètre de permission
$compteurs_visibles = wp_count_posts( 'article', 'readable' );
Avec 'readable' en second argument, WordPress applique un filtre supplémentaire sur les statuts privés, pour ne renvoyer que ce que l’utilisateur courant peut effectivement consulter. Sans ce paramètre, la fonction renvoie par défaut l’ensemble des compteurs, y compris pour des statuts privés que l’utilisateur courant ne pourrait pas consulter en détail.
Avant d’écrire une requête SQL personnalisée pour un simple total par statut, vérifier ce que
wp_count_posts()renvoie déjà évite de dupliquer une logique de comptage — et son cache — qui existe nativement.
En résumé
Ce genre de fonction discrète évite de réinventer une requête SQL pour un besoin déjà couvert, avec en prime une mise en cache native qui protège les performances d’un tableau de bord consulté fréquemment. Le réflexe à garder : chercher d’abord du côté des fonctions natives avant d’écrire sa propre requête sur mesure.