3v4l.org

run code in 300+ PHP versions simultaneously
<?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);

preferences:
24.24 ms | 408 KiB | 5 Q