Skip to content

nspl\args

Ihor Burlachenko edited this page May 19, 2016 · 1 revision

Helps to validate function arguments


expects($constraints, $arg, $atPosition = null, $otherwiseThrow = '\InvalidArgumentException')

Checks that argument satisfies the required constraints otherwise throws the corresponding exception

$constraints are callable(s) which return(s) true if the argument satisfies the requirements or it also might contain the required class name(s)
If $atPosition is null then position is calculated automatically comparing given argument to the actual arguments passed to the function
$otherwiseThrow defines exception which will be thrown if given argument is invalid, it can be the exception class or exception object

use const \nspl\args\int;
use const \nspl\args\string;
use const \nspl\args\arrayAccess;
use function \nspl\args\expects;

function nth($sequence, $n)
{
    expects([arrayAccess, string], $sequence);
    expects(int, $n);

    return $sequence[$n];
}

nth('hello world', 'blah');

Outputs:

InvalidArgumentException: Argument 2 passed to nth() must be integer, string 'blah' given in /path/to/example.php on line 17

Call Stack:
    0.0002     230304   1. {main}() /path/to/example.php:0
    0.0023     556800   2. sqr() /path/to/example.php:17
expectsAll($constraints, array $args, array $atPositions = [], $otherwiseThrow = '\InvalidArgumentException')

Checks that all specified arguments satisfy the required constraints otherwise throws the corresponding exception

use const \nspl\args\numeric;
use function \nspl\args\expects;

function sum($x, $y)
{
    expectsAll(numeric, [$x, $y]);

    return $x + $y;
}
expectsOptional($constraints, $arg, $atPosition = null, $otherwiseThrow = '\InvalidArgumentException')

Checks that argument is null or satisfies the required constraints otherwise throws the corresponding exception

function splitBy($string, $separator = ' ', $limit = null)
{
    expectsAll(string, [$string, $separator]);
    expectsOptional(int, $limit);

    return explode($separator, $string, $limit);
}
Predefined constraints

The module provides predefined constraints. Which can be one of the two types:

  • OR-constraints which are evaluated with or operator (e.g. expects([int, string], $arg) evaluates as $arg has to be an int or a string)
  • AND-constraints which are evaluated with and operator (e.g. expects([string, longerThan(3), shorterThan(10)], $arg) evaluates as $arg has to be a string longer than 3 characters and shorter than 10 characters). If you want to evaluate several AND-constraints as they were OR-constraints you can use any constraint. If you want to evaluate several OR-constraints as they were AND-constraints you can use all constraint
Callback Explanation Type
bool Checks that argument is a bool OR
int Checks that argument is an int OR
float Checks that argument is a float OR
numeric Checks that argument is numeric OR
string Checks that argument is a string OR
array_ Checks that argument is an array OR
object Checks that argument is an object OR
callable_ Checks that argument is callable OR
arrayKey Checks that argument can be an array key OR
traversable Checks that argument can be traversed with foreach OR
arrayAccess Checks that argument supports array index access OR
nonEmpty Checks that argument is not empty AND
positive Checks that argument is positive (> 0) AND
nonNegative Checks that argument is not negative (>= 0) AND
nonZero Checks that argument is not zero (!== 0) AND
any(constraint1, ..., constraintN) Checks constraints as if they were OR-constraints AND
all(constraint1, ..., constraintN) Checks constraints as if they were AND-constraints AND
not(constraint1, ..., constraintN) Checks that argument does't satisfy all listed constraints AND
values(value1, ..., valueN) Checks that argument is one of the specified values AND
longerThan($threshold) Checks that string argument is longer than given threshold AND
shorterThan($threshold) Checks that string argument is shorter than given threshold AND
biggerThan($threshold) Checks that number is bigger than given threshold AND
smallerThan($threshold) Checks that number is smaller than given threshold AND
hasKey($key) Checks that argument supports array index access and has given key AND
hasKeys($key1, ..., $keyN) Checks that argument supports array index access and has given keys AND
hasMethod($method) Checks that argument is an object and has given method AND
hasMethods($method1, ..., $methodN) Checks that argument is an object and has given methods AND
function setUsername($username)
{
    expects([string, longerThan(3), shorterThan(10)], $username);
    // ...
}

function setState($state)
{
    expects(values('running', 'idle', 'stopped'), $state);
    // ...
}    

Duck-typing example:

class Service
{
    // ...
    public function setCache($cache)
    {
        expects(withMethods('set', 'get'), $cache);
        $this->cache = $cache;
    }
    // ....
}
Custom constraints

It is possible to use custom constraints. Just define a new function which returns true when argument satisfies the constraint:

function even($value)
{
    return is_int($value) && $value %2 === 0;
}

function half($number)
{
    expects('even', $number);
    return $number / 2;
}

or we can make it more convenient to use introducing a constant:

const even = 'even';

function half($number)
{
    expects(even, $number);
    return $number / 2;
}

half('pie');

Outputs:

InvalidArgumentException: Argument 1 passed to half() must be even, string 'pie' given in /path/to/example.php on line 25

Call Stack:
    0.0009     253640   1. {main}() /path/to/example.php:0
    0.0123     673984   2. half() /path/to/example.php:25

If you need to create a constraint which takes arguments you must create a callable object which implements \nspl\args\Constraint interface. It contains two methods:

  • __invoke($value) - returns true if the value satisfies the constraint
  • __toString() - returns text which will be used in the exception when value doesn't satisfy the constraint. The text must contain message which goes after "must" in the exception message.
Clone this wiki locally