Go to file
2011-02-07 15:21:58 -02:00
library Prototype for ValidationException contexts (messages contextualized for forms, APIs, command line, translation, etc) 2011-02-07 15:21:58 -02:00
tests Hide exception messages on tests 2011-02-07 12:23:24 -02:00
.gitignore Rules for types: array, object, instances 2010-11-08 22:37:50 -02:00
README.md Better docs, quick reference 2011-02-07 12:46:08 -02:00

Respect Validation

Respect\Validation is the most awesome validation engine ever created for PHP. Featuring:

  • Fluent/Chained builders
  • Composite validation (nested, grouped and related rules)
  • Informative, awesome exceptions
  • More than 30 fully tested validators
  • PHP 5.3 only
  • Possible integration with Zend 2.0 and Symfony 2.0 validators

Roadmap

  • Custom validators (create your own validation rules and exceptions)
  • Validation message improvements (translation, contextualization)

Feature Guide

Namespace import

Respect\Validation is namespaced, but you can make your life easier by importing a single class into your context:

<?php
use Respect\Validation\Validator as v;

Simple validation

The Hello World validator is something like this:

$number = 123;
v::numeric()->validate($number); //true

Chained validation

It is possible to group and chain several validators:

//From 1 to 15 non-whitespace alphanumeric characters 
$validUsername = v::alnum()
                  ->noWhitespace()
                  ->length(1,15);

$validUsername->validate('alganet'); //true

Validating object attributes

You can validate attributes of objects or keys of arrays and its values too:

$validUser = v::attribute('username', $validUsername)    //reusing!
              ->attribute('birthdate', v::date('Y-m-d'));

$user = new \stdClass;
$user->username = 'alganet';
$user->birthdate = '1987-07-01';

$validUser->validate($user); //true

Validator reuse (works on nested, big validators too!)

Once created, you can reuse your validator anywhere:

$validUsername->validate('respect');            //true
$validUsername->validate('alexandre gaigalas'); //false 
$validUsername->validate('#$%');                //false 

Cool, informative exceptions

Respect\Validation produces a tree of validation messages that reflects the groups, nests and composite validators you declared. The following code:

try {
    $validUsername->assert('really messed up screen#name');
} catch(\InvalidArgumentException $e) {
   echo $e->getFullMessage();
}

Produces this message:

\-None of 3 required rules passed
  |-"really messed up screen#name" does not contain only letters, digits and "_"
  |-"really messed up screen#name" contains whitespace
  \-"really messed up screen#name" length is not between 1 and 15

Validation Methods

There are three different ways to validate something:

$validUsername->validate('alganet'); //returns true or false (quicker)
$validUsername->check('alganet');    //throws only the first error found (quicker)
$validUsername->assert('alganet');   //throws all of the errors found (slower)

Message finding on nested Exceptions

Nested exceptions are cool, but sometimes you need to retrieve a single message from the validator. In these cases you can use the findRelated() method. Consider the following scenario:

$validBlogPost = v::object()
                  ->attribute('title',  v::string()->length(1,32))
                  ->attribute('author', $validUser)                 //reuse!
                  ->attribute('date',   v::date())
                  ->attribute('text',   v::string());

$blogPost = new \stdClass;
$blogPost->author = clone $validUser;
$blogPost->author->username = '# invalid #';

Then, the following validation code:

try {
    $validBlogPost->assert($blogPost);
} catch (\InvalidArgumentException $e) {
    echo $e->findRelated('author', 'username', 'noWhitespace')->getMainMessage();
}

Finds the specific noWhitespace message inside author->username and prints it:

"# invalid #" contains whitespace

Using Zend and/or Symfony validators

It is also possible to reuse validators from other frameworks (you need to put them in your autoload routines):

$validHostName = v::zend('hostname')->assert('google.com');
$validTime     = v::sf('time')->assert('22:00:01');

Quick Reference

A quick, possibly incomplete, list of validators and use reference:

Alphanumeric:

v::alnum()->assert('abc 123');
v::alnum('_|')->assert('a_bc _1|23');

Alpha chars:

v::alpha()->assert('ab c');
v::alpha('.')->assert('a. b.c');

Check if it is an array (works on every Traversable, Countable ArrayAccess):

v::arr()->assert(array());
v::arr()->assert(new \ArrayObject);

An attribute of an object ant its value:

$myObject = new \stdClass;
$myObject->foo = "bar";
v::attribute("foo", v::string())->assert($myObject);

Between (works on numbers, digits and dates):

v::between(5, 15)->assert(10);
v::between('a', 'f')->assert('b');

A value after a function call (works with closures):

v::call('implode', v::int())->assert(array(1, 2, 3, 4));

Validates using the return of a callback:

v::callback('is_string')->assert('something');

Dates and date formats:

v::date('Y-m-d')->assert('2010-10-10');
v::date()->assert('Jan 10 2008');

Strings with digits:

v::digits()->assert('02384');

Iterates and validates each element:

v::each(v::hexa())->assert(array('AF', 'D1', '09'));

Check for equality:

v::equals('foobar')->assert('foobar');

Float numbers

v::float()->assert(1.5);

Hexadecimals:

v::hexa()->assert('FAFAF');

Checks if a value is inside a set:

v::in(array(1, 1, 2, 3, 5, 8))->assert(5);

Checks if an object is instance of a specific class or interface:

v::instance('\stdClass')->assert(new \stdClass);

Integer numbers:

v::int()->assert(1548);

IP addresses:

v::ip()->assert('200.226.220.222');

Length of strings, arrays or everything Countable:

v::length(5, 10)->assert('foobar');
v::length(5, 10)->assert(array(1, 2, 3, 4, 5));

Max and Min:

v::max(5)->assert(3);
v::min(5)->assert(7);

Positive and Negative:

v::negative()->assert(-5);
v::positive()->assert(3);

Whitespace, empty and null

v::noWhitespace()->assert('abc');
v::notEmpty()->assert('aaa');
v::nullValue()->assert(null);

Numeric values of all kinds:

v::numeric()->assert(1.56e-5);

Objects:

v::object()->assert(new \DateTime());

Regex evaluations:

v::regex('^[a-f]+$')->assert('abcdef');

Strings:

v::string()->assert('Hello World');

AllOf (checks all validators inside a composite):

v::allOf(
    v::string(), //any string v::length(5, 20), //between 5 and 20 chars
    v::noWhitespace()   //no whitespace allowed
)->assert('alganet');

v::string()
 ->length(5, 20)
 ->noWhitespace()
 ->assert('alganet');

OneOf (checks for one valid inside of a composite):

$v = v::oneOf(
    v::int()->positive(),   //positive integer or;
    v::float()->negative(), //negative float or; 
    v::nullValue()          //null
);
$v->assert(null); //true
$v->assert(12);   //true
$v->assert(-1.1); //true