Search by

sopheos / pebble_validation

sopheos

Form validation library: typed fields, chainable rules, error codes and messages

Package info

github.com/sopheos/pebble_validation

pkg:composer/sopheos/pebble_validation

Statistics

Installs: 436

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

1.1.4 2026-10-06 12:45 UTC

README

Validation de formulaires pour PHP 8.1+ : des champs typés qui nettoient et convertissent la saisie, des règles chaînables, et un Form qui expose valeurs, codes d'erreur et messages.

La lib ne lit pas les superglobales, ne traduit pas les messages et ne produit pas de HTML : on lui passe un tableau ($_POST, JSON décodé…), on récupère des valeurs typées et des codes d'erreur.

Installation

composer require sopheos/pebble_validation

Extensions requises : mbstring, fileinfo, filter. imagick est facultative : si elle est chargée, elle mesure les images à la place de getimagesize().

Claude Code

Ce package fournit un skill Claude Code dans skills/pebble-validation/. Il documente les patterns d'usage et les pièges de la librairie : codes d'erreur égaux aux noms de règles, defaultValue() non validée, custom() qui n'échoue qu'en levant une exception, conversions du mode auto de Table, IsVatNumber et IsPostalCode mal ancrés, etc.

Dans un projet qui dépend de sopheos/pebble_validation, copie-le une fois dans .claude/skills/ après composer install pour que Claude Code le charge automatiquement. Le nom du dossier doit correspondre au name déclaré dans SKILL.md :

cp -r vendor/sopheos/pebble_validation/skills/pebble-validation .claude/skills/pebble-validation

Pour la maintenance de la lib elle-même, voir CLAUDE.md. Les bugs connus sont listés dans TODO.md.

Exemple

use Pebble\Validation\Form;
use Pebble\Validation\Fields\Integer;
use Pebble\Validation\Fields\Text;
use Pebble\Validation\Rules\IsEmail;

$form = new Form();
Text::create('email')->required()->addRule(IsEmail::create())->addTo($form);
Integer::create('age')->min(18)->addTo($form);

$form->field('email')->setMessage('required', 'E-mail obligatoire');

if (!$form->validate($_POST)) {
    $form->errors();   // ['email' => 'required', 'age' => 'num_min']
    $form->messages(); // ['email' => 'E-mail obligatoire', 'age' => 'default']
}

$form->values();       // ['email' => 'john@doe.fr', 'age' => 42]

Form

\Pebble\Validation\Form regroupe des champs indexés par leur nom.

  • addField(FieldInterface $field) : static Ajoute un champ. Un champ de même nom remplace le précédent. Équivalent : $field->addTo($form).
  • field(string $name) : ?FieldInterface / fields() : array Un champ, ou tous.
  • validate(array $data) : bool Valide chaque champ avec $data[$nom] ?? null. Tous les champs sont validés, même après un échec.
  • isValid() : bool Résultat de la dernière validation.
  • values() : array Valeurs nettoyées et converties de tous les champs, y compris invalides.
  • inputs() : array Saisies après nettoyage, avant les règles. Les saisies falsy ("0", 0, false) sont omises (voir TODO.md).
  • errors() : array Codes d'erreur des champs invalides.
  • messages() : array Messages des champs invalides.
  • value(string $field) / input(string $field) / error(string $field) / message(string $field) Accès à un champ. null si le champ n'existe pas.
  • setName(string $name) : static / name() : string Nom libre du formulaire.

Fields

Tous les champs héritent de \Pebble\Validation\Fields\Field et se construisent avec Champ::create('nom').

Cycle de validate($value) :

  1. prepare() nettoie et convertit la saisie. Si elle n'est pas convertible, l'erreur est default.
  2. Si la valeur est vide (null, '', []) : erreur required si le champ est requis, sinon defaultValue() est appliquée sans passer par les règles.
  3. Les règles s'exécutent dans l'ordre d'ajout. Chacune peut transformer la valeur. La première qui échoue donne son nom comme code d'erreur.

Méthodes communes :

  • required() : static Rend le champ obligatoire (erreur required).
  • defaultValue($value) : static Valeur utilisée si la saisie est vide.
  • addRule(RuleInterface $rule) : static Ajoute une règle.
  • custom(string $name, callable $callable, ...$params) : static Règle maison : $callable($value, ...$params) renvoie la nouvelle valeur. Elle échoue uniquement si elle lève une exception.
  • fakeRule(string $name) : static Règle qui passe toujours, pour réserver un code d'erreur posé ensuite par setError().
  • setMessage(string $rule, ?string $message = null) : static Message pour un code d'erreur. Sans message, le code lui-même.
  • setDefaultMessage(string $message) : static Message des codes sans message (par défaut default).
  • setError(string $error) : static / setValue($value) : static Forcent l'erreur ou la valeur après validation.
  • value() / input() / error() : string / message() : string / isValid() : bool / rules() : array.

Textarea, Text, Password

  • Textarea Texte multiligne. Décode les entités HTML, retire les balises, les caractères de contrôle et les espaces spéciaux, réduit les espaces et garde au plus une ligne vide.
  • Text Comme Textarea, sur une seule ligne. Ajoute isFile(string $prefix = '', string $suffix = '') et isDir(...).
  • Password Comme Text, mais ni balises retirées ni trim. Refuse les espaces (whitespace) et les espaces spéciaux (special_space).

Règles : min(int) (len_min), max(int) (len_max), range(int, int) (len_range), equal(int) (len_len), match(string) (match), differ(string) (differ), includes(array) (includes), excludes(array) (excludes), regexMatch(string $name, string $pattern) et regexDiff(...) (code $name).

Textarea::sanitize(string $input, bool $multiline = false, bool $striptags = true) : string est utilisable seule.

Url, Uuid

  • Url Text nettoyé par FILTER_SANITIZE_URL (les espaces sont supprimés), avec la règle is_url.
  • Uuid Text avec la règle format.

Integer, Number, Timestamp

  • Integer Cast (int) de toute valeur numérique : "1.9" donne 1, "1e3" donne 1000.
  • Number Cast (float). Le séparateur décimal est le point.
  • Timestamp Integer qui accepte aussi une date ISO 8601, convertie par strtotime().

Règles : min() (num_min), max() (num_max), range() (num_range), equal() (match), diff() (differ), includes(), excludes().

Boolean

Accepte true/false, 0/1 et les chaînes de FILTER_VALIDATE_BOOLEAN (on, yes, off, no…). false n'est pas une valeur vide.

  • isTrue() / isFalse() Règle match, par exemple pour des CGU à accepter.

Table

Tableau PHP ou chaîne JSON. Chaque élément est converti selon le mode :

  • auto (par défaut) Les chaînes numériques deviennent des float (voir TODO.md), les autres chaînes sont nettoyées comme un Textarea.
  • none() Aucune conversion.
  • integer() / number() / text() / textarea() / timestamp() Conversion comme le champ du même nom.

Règles : min(int) (array_min), max(int) (array_max), range(int, int) (array_range), map(Rule $rule) (applique une règle à chaque élément), includes(array), excludes(array), customMap(string $name, callable $callable, ...$params).

Sous-formulaires :

  • child(Form $form) : static Valide un objet avec $form (erreur child). Les erreurs détaillées se lisent sur $form.
  • children(Form $form) : static Valide une liste d'objets (erreur children).
  • childrenErrors() : array / childrenMessages() : array Erreurs des éléments invalides, indexées par position.

Upload

Entrée de $_FILES. Les erreurs PHP sont traduites : taille (file_size), envoi partiel ou absent (corrupted), autre (default, avec une notice). Un champ facultatif sans fichier échoue avec corrupted : passer null dans ce cas (voir TODO.md).

  • mimes(array $mimes) Types MIME ou extensions (['jpg', 'png', 'application/pdf']), lus dans le contenu du fichier (file_type).
  • size(int $limit) Taille maximale en octets (file_size). Un fichier vide échoue.
  • min(int $width, int $height, bool $ignoreOrientation = true) / max(...) Dimensions d'image (image_min_size, image_max_size).

Rules

Toutes les règles sont dans \Pebble\Validation\Rules, se construisent avec create(...) et s'ajoutent par $field->addRule(). Le nom de la règle est le code d'erreur.

  • Longueur : LenMin, LenMax, LenRange, LenEqual (len_len).
  • Nombres : NumMin, NumMax, NumRange.
  • Tableaux : ArrayMin, ArrayMax, ArrayRange, ArrayMap, Child, Children.
  • Comparaison : Exact (match), Differ, Includes, Excludes (comparaison non stricte).
  • Formats : Regex(string $name, string $pattern, bool $match = true), IsEmail (met en minuscules), IsUrl, IsIP(int $flags = 0), Uuid (format), IsPostalCode(string $country) (code pays ISO en majuscules), IsVatNumber (numéro de TVA intracommunautaire), CharList (caractères autorisés, voir ci-dessous).
  • Fichiers : IsFile, IsDir, FileType, FileSize, ImageMinSize, ImageMaxSize.
  • Code utilisateur : CallableRule (échoue si une exception est levée, c'est custom()), Callback (échoue si le callable renvoie null), FakeRule.

CharList::create(string $name = 'charlist') se compose avec letters(), numbers(), accents(), ponctuations(), currencies(), indices(), text() (tout cela), emoji() et add(string $chars) (fragment de classe de caractères regex, non échappé). Les espaces sont toujours acceptés.

IsVatNumber et IsPostalCode (GB, CR, LI) acceptent du texte autour d'une valeur valide : voir TODO.md.

TestHelper

\Pebble\Validation\TestHelper vérifie la configuration d'un formulaire dans les tests d'un projet. Il appelle les assertions de PHPUnit, qui doit donc être installé (ce n'est qu'une dépendance de développement de la lib).

  • fields(FormInterface $form, array $tests, array $required = []) $tests : ['nom' => Classe::class]. Vérifie la liste exacte des champs, leur classe et les champs requis.
  • rules(FieldInterface $field, array $tests) $tests : ['nom_regle' => ['propriete' => valeur]]. Vérifie la liste exacte des règles et de leurs propriétés.
  • formRules(FormInterface $form, array $tests) rules() pour chaque champ : ['champ' => ['nom_regle' => [...]]].

Tests

composer install
vendor/bin/phpunit

Les bugs connus sont figés par des tests annotés // BUG: qui vérifient le comportement actuel.