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);
Output for 8.2.0 - 8.2.19, 8.3.0 - 8.3.7
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.
Output for 7.4.33, 8.0.1 - 8.0.30, 8.1.0 - 8.1.28
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" } } Array ( ) object(stdClass)#3 (4) { ["name"]=> string(5) "Vasya" ["surname"]=> string(5) "Popov" ["age"]=> string(2) "33" ["address"]=> object(stdClass)#4 (2) { ["street"]=> string(8) "Pushkina" ["house"]=> string(12) "Kolotushkina" } } Array ( [age] => Array ( [0] => Wrong json value type. Expected: "int" received: "string" value: "33" ) ) object(stdClass)#2 (3) { ["name"]=> string(5) "Vasya" ["surname"]=> string(5) "Popov" ["address"]=> object(stdClass)#1 (2) { ["street"]=> string(8) "Pushkina" ["house"]=> string(12) "Kolotushkina" } } Array ( [age] => Array ( [0] => Undefined property: stdClass::$age ) ) object(stdClass)#4 (2) { ["name"]=> string(5) "Vasya" ["surname"]=> string(5) "Popov" } Array ( [age] => Array ( [0] => Undefined property: stdClass::$age ) [address] => Array ( [0] => Undefined property: stdClass::$address ) )

preferences:
108.97 ms | 405 KiB | 92 Q