<?php
$userJson = '{
"name":"Vasya",
"surname":"Popov",
"age":33,
"address":{
"street":"Pushkina",
"house":"Kolotushkina"
}
}';
$badUserJson = '{
"name":"Vasya",
"surname":"Popov",
"age":"33",
"address":{
"street":"Pushkina",
"house":"Kolotushkina"
}
}';
$noAgeUserJson = '{
"name":"Vasya",
"surname":"Popov",
"address":{
"street":"Pushkina",
"house":"Kolotushkina"
}
}';
$noAddressUserJson = '{
"name":"Vasya",
"surname":"Popov"
}';
/**
* @property-read string $name
* @property-read string $surname
* @property-read AddressData $address
*/
class UserData {}
/**
* @property-read string $street
* @property-read string $house
*/
class AddressData {}
class JsonValidator
{
protected const IS_STRING = 'static::isString';
protected const IS_INT = 'static::isInt';
protected static $assertions = [];
protected static function isString($value) : void
{
if (false === is_string($value)) {
throw new Exception(
'Wrong json value type. Expected: "string" received: "' . gettype($value) . '" value: "' . $value . '"'
);
}
}
protected static function isInt($value) : void
{
if (false === is_int($value)) {
throw new Exception(
'Wrong json value type. Expected: "int" received: "' . gettype($value) . '" value: "' . $value . '"'
);
}
}
public static function validate(object $data): array
{
$allErrors = [];
set_error_handler(static function($errno, $errstr, $errfile, $errline) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});
foreach (static::$assertions as $parameterName => $assertionFunction) {
try {
$parameterValue = $data->$parameterName;
$errors = call_user_func($assertionFunction, $parameterValue);
} catch (Throwable $exception) {
$allErrors[$parameterName][] = $exception->getMessage();
}
if (isset($errors) && count($errors)) {
$allErrors[$parameterName] = $errors;
}
}
restore_error_handler();
return $allErrors;
}
}
class UserDataValidator extends JsonValidator
{
private const IS_ADDRESS = 'AddressDataValidator::validate';
protected static $assertions = [
'name' => self::IS_STRING,
'surname' => self::IS_STRING,
'age' => self::IS_INT,
'address' => self::IS_ADDRESS,
];
}
class AddressDataValidator extends JsonValidator
{
protected static $assertions = [
'street' => self::IS_STRING,
'house' => self::IS_STRING,
];
}
/** @var UserData $userData */
$userData = json_decode($userJson, false);
var_dump($userData);
$errors = UserDataValidator::validate($userData);
print_r($errors);
/** @var UserData $userData */
$userData = json_decode($badUserJson, false);
var_dump($userData);
$errors = UserDataValidator::validate($userData);
print_r($errors);
/** @var UserData $userData */
$userData = json_decode($noAgeUserJson, false);
var_dump($userData);
$errors = UserDataValidator::validate($userData);
print_r($errors);
/** @var UserData $userData */
$userData = json_decode($noAddressUserJson, false);
var_dump($userData);
$errors = UserDataValidator::validate($userData);
print_r($errors);
- Output for git.master, git.master_jit, rfc.property-hooks
- object(stdClass)#1 (4) {
["name"]=>
string(5) "Vasya"
["surname"]=>
string(5) "Popov"
["age"]=>
int(33)
["address"]=>
object(stdClass)#2 (2) {
["street"]=>
string(8) "Pushkina"
["house"]=>
string(12) "Kolotushkina"
}
}
Process exited with code 137.
This tab shows result from various feature-branches currently under review by the php developers. Contact me to have additional branches featured.
Active branches
Archived branches
Once feature-branches are merged or declined, they are no longer available. Their functionality (when merged) can be viewed from the main output page
preferences:
31.01 ms | 405 KiB | 5 Q