# register_rest_route avec un schema mal typé : l’erreur silencieuse

> Un argument de route déclaré sans validate_callback laisse passer des données incohérentes sans jamais déclencher d'erreur visible côté API.

- Auteur : WordPress Développement
- Publié le : 2020-05-05
- Mis à jour le : 2020-05-05
- Catégorie : Headless &amp; API
- URL : https://www.wpmoderne.fr/headless/register-rest-route-schema-mal-type-erreur-silencieuse/

## L’essentiel

- Un type déclaré sans validate_callback n'est pas vérifié à l'exécution
- sanitize_callback transforme la donnée sans jamais la refuser
- La combinaison des deux callbacks évite l'acceptation silencieuse

« 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

> L'essentiel à retenir : Un type déclaré sans validate_callback n'est pas vérifié à l'exécution ; sanitize_callback transforme la donnée sans jamais la refuser ; La combinaison des deux callbacks évite l'acceptation silencieuse

```
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`, `maximum` ou `enum`
- 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.
