Make PHP array data validation easier and clearer by defining array structures.
We often need to receive, validate, and process data objects. Sometimes, an array might be too dumb for the task at hand, requiring several unpleasant control structures to validate and setup. Moreover, creating a dedicated DTO class (or more) might be overkill, requiring a lot of boilerplate code, whilst making things like error messaging and future refactoring more difficult.
In cases like this I find myself itching for a Go/Rust like struct instead.
See doc for a more in depth discussion.
composer require safe-k/struct-arrayTo define and validate an array data structure, first create a Struct - this requires a name, used for error messaging, and an interface - then use the provided Validator function to validate the data against the defined Struct.
A Struct's interface ia an array consisting of string keys (matching the expected property names) and callable values. These values can be any callable PHP entity, and is expected to accept a single mixed type $value, and return a bool. Some valid examples are:
is_*variable handling functions (is_string,is_int,is_callableetc.)- A
Closure(function ($value): bool {}) - A class with an
__invoke($value): boolmethod
Here's an example written using the provided convenient helper functions:
<?php use SK\StructArray\Exception\StructValidationException; use function SK\StructArray\{ arrayOf, optional, not, struct, validate }; $directory = [ 'path' => __DIR__, 'content' => [ [ 'header' => 'Greeting', 'line' => 'Hello', ], ] ]; try { validate($directory, struct('Directory', [ 'path' => 'is_dir', 'file' => optional('is_file', __DIR__ . '/README.md'), 'content' => arrayOf(struct('Paragraph', [ 'header' => 'is_string', 'line' => not('is_null'), ])), ])); } catch (StructValidationException $e) { echo $e->getMessage() . PHP_EOL; return; } echo "Path: {$directory['path']}" . PHP_EOL; echo "File: {$directory['file']}" . PHP_EOL; // Prints: // Path: /Users/seifkamal/src/struct-array // File: /Users/seifkamal/src/struct-array/README.mdHere's the same one using static class methods:
<?php use SK\StructArray\Exception\StructValidationException; use SK\StructArray\Property\Type; use SK\StructArray\Struct; use SK\StructArray\Validator; $directory = [ 'path' => __DIR__, 'content' => [ [ 'header' => 'Greeting', 'line' => 'Hello', ], ] ]; $paragraphStruct = Struct::of('Paragraph', [ 'header' => 'is_string', 'line' => Type::not('is_null'), ]); $directoryStruct = Struct::of('Directory', [ 'path' => 'is_dir', 'file' => Type::optional('is_file', __DIR__ . '/README.md'), 'content' => Type::arrayOf($paragraphStruct), ]); try { Validator::validate($directory, $directoryStruct); } catch (StructValidationException $e) { echo $e->getMessage() . PHP_EOL; return; } echo "Path: {$directory['path']}" . PHP_EOL; echo "File: {$directory['file']}" . PHP_EOL; // Prints: // Path: /Users/seifkamal/src/struct-array // File: /Users/seifkamal/src/struct-array/README.mdFor more, see the examples directory.