« Pourquoi cette route accepte-t-elle une chaîne de caractères alors que le schéma déclare un entier ? » C’est la question qui revient le plus souvent quand un contrôleur REST personnalisé se met à stocker des valeurs incohérentes sans jamais lever d’erreur. La réponse tient en une ligne manquante : déclarer un type dans le schéma d’argument de register_rest_route() ne suffit pas à faire respecter ce type.
Ce malentendu touche une bonne partie des développeurs qui découvrent la validation des arguments REST. Le tableau args ressemble à un schéma strict, avec ses clés type, required, default. Il en a l’apparence, mais pas tout à fait le comportement, tant que deux clés précises ne sont pas explicitement renseignées.
Ce que fait vraiment le champ type
Dans un tableau d’arguments de route, la clé type sert avant tout à documenter le schéma exposé publiquement via OPTIONS sur la route, et à alimenter la génération de la documentation de l’API. Elle n’active pas, seule, une vérification systématique de la valeur reçue. Le contrôle réel de la donnée passe par deux callbacks distincts, tous deux facultatifs : validate_callback, qui décide si la valeur est acceptable, et sanitize_callback, qui la transforme avant qu’elle atteigne le code du contrôleur.
Sans validate_callback, une route qui déclare 'type' => 'integer' pour son paramètre quantite acceptera parfaitement la chaîne "trois" sans lever la moindre erreur 400. Le contrôleur recevra cette chaîne telle quelle dans $request->get_param( 'quantite' ), et c’est seulement au moment de l’utiliser — une multiplication, une insertion en base — que le bogue se manifestera, souvent loin du point d’entrée et donc difficile à relier à l’origine réelle du problème.
Un schéma qui rassure à tort

register_rest_route( 'commande/v1', '/lignes', array(
'methods' => 'POST',
'callback' => 'creer_ligne_commande',
'args' => array(
'quantite' => array(
'type' => 'integer',
'required' => true,
// ni validate_callback, ni sanitize_callback : le type n'est qu'indicatif
),
),
) );
Ce schéma se lit comme une garantie forte. Il n’en est pourtant qu’une intention. WordPress ne rejette pas automatiquement une valeur qui ne correspond pas au type déclaré tant que le mécanisme de schéma REST natif n’est pas explicitement activé pour ce faire, et cette activation reste peu documentée en dehors des contrôleurs qui héritent de WP_REST_Controller et de son intégration plus poussée avec rest_validate_value_from_schema().
La correction : combiner les deux callbacks
'args' => array(
'quantite' => array(
'type' => 'integer',
'required' => true,
'validate_callback' => function( $valeur, $request, $param ) {
return is_numeric( $valeur ) && (int) $valeur > 0;
},
'sanitize_callback' => 'absint',
),
),
Avec cette version, une valeur non numérique déclenche désormais une réponse 400 explicite, avant même que le callback principal ne soit exécuté. sanitize_callback se charge ensuite de convertir la valeur validée en entier propre via absint(), garantissant que le contrôleur ne manipule jamais autre chose qu’un entier positif.
Utiliser rest_validate_value_from_schema pour aller plus loin
Pour un schéma plus riche — avec minimum, maximum, enum ou pattern — la fonction interne rest_validate_value_from_schema() peut être appelée directement comme validate_callback, ce qui évite de réécrire à la main une validation que WordPress sait déjà faire à partir du schéma déclaré :
- Déclarer un schéma complet avec
minimum,maximumouenum - Passer
'validate_callback' => 'rest_validate_value_from_schema' - Laisser WordPress comparer la valeur reçue à l’ensemble du schéma déclaré, plutôt qu’à une seule condition écrite à la main
Repérer le problème sur un projet existant
Sur un projet déjà en production, le symptôme le plus fréquent est une donnée incohérente en base, découverte tardivement, sans qu’aucune ligne de log REST ne signale de refus de requête. Un audit rapide consiste à relire chaque tableau args des routes personnalisées et à vérifier la présence effective de validate_callback pour chaque paramètre dont le type est sensible — identifiants numériques, énumérations, dates. La seule présence de type ne doit jamais être interprétée comme une garantie de validation.
En résumé
Le schéma d’arguments de register_rest_route() documente une intention, il ne l’applique pas seul. Tant que validate_callback et sanitize_callback ne sont pas renseignés, une route accepte silencieusement des valeurs qui ne correspondent pas au type annoncé, ce qui déplace le bogue loin de son origine. La correction tient en quelques lignes, mais suppose de le savoir avant d’écrire le schéma, pas après avoir traqué une donnée corrompue en base.