Faut-il vraiment retourner un objet WP_REST_Response depuis une route personnalisée, ou un simple tableau associatif fait-il l’affaire ? La documentation de WordPress accepte les deux formes sans se prononcer clairement, et beaucoup de développeurs choisissent le tableau par réflexe, parce que c’est la solution la plus rapide à écrire. Le résultat fonctionne, la réponse JSON est bien formée, les tests passent. Alors où est la différence ?
Elle se niche dans tout ce qui entoure la donnée elle-même : le code de statut HTTP, les en-têtes, les liens hypermédia, et la possibilité pour d’autres extensions de modifier la réponse après coup. Un tableau brut n’offre aucune de ces capacités ; il est transformé en JSON tel quel, avec un statut 200 par défaut, point final.
Ce que permet réellement l’objet
Quand un callback de route retourne un tableau, WordPress l’enveloppe automatiquement dans une réponse avec le statut 200. C’est suffisant pour un cas simple, mais insuffisant dès qu’il faut renvoyer un code 201 après une création, un 202 pour un traitement asynchrone, ou ajouter un en-tête personnalisé comme X-Cache-Status. L’objet WP_REST_Response, qui étend WP_HTTP_Response, expose justement les méthodes nécessaires pour cela : set_status(), header(), get_data() et surtout add_link().
La méthode add_link() est particulièrement précieuse pour un front headless : elle permet de construire la section _links de la réponse, celle-là même qui rend possible le mécanisme _embed. Un tableau brut ne génère jamais cette section, ce qui coupe le client de toute possibilité d’embarquement des ressources liées.
Un exemple concret

Comparons les deux approches sur une route qui renvoie la météo d’un site associée à un article :
// Version tableau : fonctionne, mais limitée
function meteo_callback( $request ) {
return array( 'temperature' => 18, 'ville' => 'Lyon' );
}
// Version objet : statut, en-tête et lien explicites
function meteo_callback( $request ) {
$response = new WP_REST_Response( array(
'temperature' => 18,
'ville' => 'Lyon',
) );
$response->set_status( 200 );
$response->header( 'Cache-Control', 'max-age=300' );
$response->add_link( 'collection', rest_url( '/meteo/v1/villes' ) );
return $response;
}
La seconde version n’ajoute que quelques lignes, mais elle rend la réponse exploitable par un client qui souhaiterait suivre le lien vers la collection, ou par un proxy de cache qui respecterait l’en-tête Cache-Control.
L’effet sur les filtres rest_prepare_*
Les filtres de la famille rest_prepare_{post_type}, très utilisés pour enrichir une réponse d’article, reçoivent en second argument l’objet WP_REST_Response déjà construit par le contrôleur de base. Sur une route personnalisée qui ne s’appuie pas sur WP_REST_Controller, ce filtre n’existe pas nativement ; mais si l’extension définit son propre point d’extension en s’inspirant du même schéma, elle a tout intérêt à travailler sur un objet WP_REST_Response plutôt que sur un tableau, ne serait-ce que pour rester cohérente avec le reste de l’écosystème REST de WordPress.
Tableau comparatif
| Capacité | Tableau brut | WP_REST_Response |
|---|---|---|
| Statut HTTP personnalisé | Non (200 forcé) | Oui, via set_status() |
| En-têtes personnalisés | Non | Oui, via header() |
| Liens hypermédia (_links) | Non | Oui, via add_link() |
| Compatible _embed côté client | Non | Oui |
| Simplicité d’écriture | Élevée | Légèrement plus verbeuse |
Quand le tableau suffit
Il serait excessif de bannir le tableau. Pour une route interne, appelée uniquement par un script d’administration ou un outil de diagnostic qui n’a besoin ni de statut différencié, ni de liens, ni de cache, le tableau reste parfaitement légitime et plus rapide à écrire. La règle pratique est simple : dès qu’une route est destinée à un front headless public, qui pourrait vouloir suivre des relations, gérer un cache ou distinguer un succès partiel d’un succès complet, l’objet WP_REST_Response devient la bonne option par défaut.
Sur nos projets, la règle qu’on applique est simple : toute route consommée par un front externe retourne un WP_REST_Response, même quand elle n’utilise au départ que la donnée brute. Ça évite une réécriture le jour où il faut ajouter un en-tête de cache.
Notre verdict
Le tableau associatif n’est pas une erreur, c’est un choix par défaut trop souvent fait sans y penser. L’objet WP_REST_Response coûte quelques lignes de plus à l’écriture, mais ouvre des possibilités que le tableau ferme définitivement : statut explicite, en-têtes, liens hypermédia, cohérence avec le reste de l’API REST de WordPress. Pour une route interne et jetable, le tableau suffit ; pour tout ce qui alimente un front découplé destiné à durer, l’objet reste le choix le plus sûr.