Every time you write some php functions or class methods, it's good practice to check input arguments and throw an exceptions, or trigger errors or warnings etc...
For example
<?php
function send_email($email, $subject, $body)
{
if (empty($email)) {
throw new InvalidArgumentException('Email should not be empty');
}
if (!is_string($email) || filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
throw new InvalidArgumentException('Email format is invalid');
}
if (empty($subject)) {
throw new InvalidArgumentException('Subject should not be empty');
}
if (!is_string($subject)) {
throw new InvalidArgumentException('Subject must be a string');
}
if (empty($body)) {
throw new InvalidArgumentException('Body should not be empty');
}
if (!is_string($body)) {
throw new InvalidArgumentException('Body must be a string');
}
return mail($email, $subject, $body);
}
As you can see most of this example contains validation code, whereas only one helpful line which do the job. You actually need to write a lot of code if you want to reliably protect your functions. And this is tediously.
My question is - does anybody know some good way to validate code easily? Is there any libraries that validate depends on PHP-DOC? For example:
<?php
/**
* @param email $email
* @param string $subject
* @param string $body
*/
function send_email($email, $subject, $body)
{
return mail($email, $subject, $body);
}
Thank you.
The easiest way in pure PHP is to simplify the check by using assertions:
class Assert {
public static function isString($var) {
if (!is_string($var)) {
throw new InvalidArgumentException('Argument is not a string');
}
}
}
function foo($string) {
Assert::isString($string);
...
}
You can spruce this up with introspection and/or debug backtraces to include more information in the thrown exception.
I don't think there are libraries that do this, but if you really want to go this way:
/**
* @param email $email
* @param string $subject
* @param string $body
*/
function send_email($email, $subject, $body)
{
check_arguments(__FUNCTION__, func_get_args());
return mail($email, $subject, $body);
}
And all the fun goes inside check_arguments()
which would parse the DocComment and match the declared types with the actual argument types:
function check_arguments($funcName, array $args){
$func = new \ReflectionFunction($funcName);
$docComment = $func->getDocComment();
// parse the comment here into a data structure,
// compare types and throw Exceptions on failure...
}
Have a look at Non-standard PHP library (NSPL). With its args module you can do the following:
use const
spl\args
otEmpty;
use const
spl\args\string;
use function
spl\args\expects;
use function
spl\args\expectsAll;
function validEmail($email)
{
return filter_var($email, FILTER_VALIDATE_EMAIL) === false
}
function send_email($email, $subject, $body)
{
expectsAll([nonEmpty, string], [$email, $subject, $body]);
expects('validEmail', $email);
return mail($email, $subject, $body);
}