As a developer, it might be of interest for you to be free from certain syntax restrictions imposed in PHP 5 and earlier. Aside from the uniformity of the syntax mentioned previously, where you'll see the most improvement in syntax is the ability to call any return value, which is callable by simply appending an extra set of parentheses. Also, you'll be able to directly access any array element when the return value is an array.
() (with or without parameters). An element can be immediately dereferenced from any function or method that returns an array by simply indicating the element using square brackets [];. In the short (but trivial) example shown next, the function test() returns an array. The array contains six anonymous functions. $a has a value of $t. $$a is interpreted as $test:function test()
{
return [
1 => function () { return [
1 => function ($a) { return 'Level 1/1:' . ++$a; },
2 => function ($a) { return 'Level 1/2:' . ++$a; },
];},
2 => function () { return [
1 => function ($a) { return 'Level 2/1:' . ++$a; },
2 => function ($a) { return 'Level 2/2:' . ++$a; },
];}
];
}
$a = 't';
$t = 'test';
echo $$a()[1]()[2](100);echo $$a()[1]()[2](100) command. This is parsed left-to-right, which executes as follows:$$a() interprets as test(), which returns an array[1] dereferences array element 1, which returns a callback() executes this callback, which returns an array of two elements[2] dereferences array element 2, which returns a callback(100) executes this callback, supplying a value of 100, which returns Level 1/2:101Application\Web\Securityclass. In the constructor, we build and define two arrays. The first array consists of filter callbacks. The second array has validation callbacks:public function __construct()
{
$this->filter = [
'striptags' => function ($a) { return strip_tags($a); },
'digits' => function ($a) { return preg_replace(
'/[^0-9]/', '', $a); },
'alpha' => function ($a) { return preg_replace(
'/[^A-Z]/i', '', $a); }
];
$this->validate = [
'alnum' => function ($a) { return ctype_alnum($a); },
'digits' => function ($a) { return ctype_digit($a); },
'alpha' => function ($a) { return ctype_alpha($a); }
];
}$security->filterDigits($item));
__call(), which gives us access to non-existent methods:public function __call($method, $params)
{
preg_match('/^(filter|validate)(.*?)$/i', $method, $matches);
$prefix = $matches[1] ?? '';
$function = strtolower($matches[2] ?? '');
if ($prefix && $function) {
return $this->$prefix[$function]($params[0]);
}
return $value;
}We use preg_match() to match the $method param against filter or validate. The second sub-match will then be converted into an array key in either $this->filter or $this->validate. If both sub-patterns produce a sub-match, we assign the first sub-match to $prefix, and the second sub-match $function. These end up as variable parameters when executing the appropriate callback.
First of all, we create a sample file, chap_02_web_filtering_ast_example.php, to take advantage of the autoloading class defined in Chapter 1, Building the Foundation, to obtain an instance of Application\Web\Security:
require __DIR__ . '/../Application/Autoload/Loader.php'; Application\Autoload\Loader::init(__DIR__ . '/..'); $security = new Application\Web\Security();
Next, we define a block of test data:
$data = [
'<ul><li>Lots</li><li>of</li><li>Tags</li></ul>',
12345,
'This is a string',
'String with number 12345',
];Finally, we call each filter and validator for each item of test data:
foreach ($data as $item) {
echo 'ORIGINAL: ' . $item . PHP_EOL;
echo 'FILTERING' . PHP_EOL;
printf('%12s : %s' . PHP_EOL,'Strip Tags', $security->filterStripTags($item));
printf('%12s : %s' . PHP_EOL, 'Digits', $security->filterDigits($item));
printf('%12s : %s' . PHP_EOL, 'Alpha', $security->filterAlpha($item));
echo 'VALIDATORS' . PHP_EOL;
printf('%12s : %s' . PHP_EOL, 'Alnum',
($security->validateAlnum($item)) ? 'T' : 'F');
printf('%12s : %s' . PHP_EOL, 'Digits',
($security->validateDigits($item)) ? 'T' : 'F');
printf('%12s : %s' . PHP_EOL, 'Alpha',
($security->validateAlpha($item)) ? 'T' : 'F');
}Here is the output of some input strings:

For more information on AST, please consult the RFC that addresses the Abstract Syntax Tree, which can be viewed at https://wiki.php.net/rfc/abstract_syntax_tree.