3v4l.org

run code in 300+ PHP versions simultaneously
<?php /** * @package at.app * @version 0.3[20151212] * @author Adrian <adrian@enspi.red> * @copyright 2014 - 2015 * @license GNU GPL V2 <http://gnu.org/licenses/gpl-2.0.txt> */ declare( strict_types = 1 ); namespace at\simple\app; use at\simple\app\api\modelable as modelableAPI; /** * base implementation of modelableAPI. * * concrete classes may define getter methods for any string <offset>, * with the following signature: * get<offset>( void ) : mixed * * concrete classes may define setter methods for any string <offset>, * with the following signature: * set<offset>( mixed $value ) : void * * concrete classes may define unsetter methods for any string <offset>, * with the following signature: * unset<offset>( void ) : void * * concrete classes may define validator methods for any string <offset>, * with the following signature: * validate<offset>( mixed $value, bool $throw ) : bool * any <offset> with a validator method must either be a literal offset, * or have a corresponding set<offset> method (@see self::offsetSet()). * if the $throw argument is TRUE, and validation fails, * the validator method must throw a DomainException. */ abstract class DomainModel extends \SPLFixedArray implements modelableAPI { /** * @const array literal property name => default value map. * if no default is specified for a property, null will be used. */ const DATA = []; /** * @const array|null list of enumerable offsets. * if null, defaults to PROP. */ const ENUM = null; /** * @const array|null list of json-serializable offsets. * if null, defaults to ENUM. */ const JSON = null; /** * @const array list of identifiable literal properties. */ const KEYS = []; /** * @const array literal property name => index map. */ const PROP = []; /** * @const array literal property name => type (data type|classname) map. */ const TYPE = []; /** * @type array runtime list of enumerable properties. */ private $_enum = []; /** * @see <http://php.net/SPLFixedArray.fromArray> */ public static function fromArray( array $array ) { return static::from_array( $array ); } /** * @see modelableAPI::from_array() */ public static function from_array( array $data ) : modelableAPI { $dataObject = new static; foreach( $array as $prop => $value ) { $dataObject->offsetSet( $prop, $value ); } return $dataObject; } public function __construct() { parent::__construct( count( self::PROP ) ); foreach( static::DATA as $prop => $default ) { $this->offsetSet( $prop, $default ); } $this->_enum = static::ENUM ?? array_keys( static::PROP ); } /** * @see <http://php.net/Iterator.current> */ public function current() { return $this->offsetGet( current( $this->_enum ) ); } /** * @see modelableAPI::getDefaults() */ public function getDefaults() : array { return static::DATA; } /** * @see modelableAPI::getKeys() */ public function getKeys() : array { $keys = []; foreach( static::KEYS as $key ) { $keys[$key] = $this->offsetGet( $key ); } return $keys; } /** * @see modelableAPI::getProperties() */ public function getProperties() : array { return $this->_enum; } /** * @see modealableAPI::getTypes() */ public function getTypes() : array { return static::TYPE; } /** * @see <http://php.net/jsonSerializable.jsonSerialize> */ public function jsonSerialize() { $props = static::JSON ?? $this->_enum; $jsonable = []; foreach( $props as $prop ) { $jsonable[$prop] = $this->offsetGet( $prop ); } return $jsonable; } /** * @see <http://php.net/Iterator.key> */ public function key() { return current( $this->_enum ); } /** * @see <http://php.net/Iterator.next> */ public function next() { next( $this->_enum ); } /** * @see <http://php.net/ArrayAccess.offsetExists> */ public function offsetExists( $offset ) { return ( method_exists( [$this, "get{$offset}"] ) || method_exists( [$this, "set{$offset}"] ) || isset( self::PROP[$offset] ) ); } /** * @see <http://php.net/ArrayAccess.offsetGet> * * @throws UnderflowException if offset does not exist or is not readable */ public function offsetGet( $offset ) { if( ! is_string( $offset ) ) { $t = gettype( $offset ); $m = "\$offset must be a string, [{$t}] provided"; throw new \InvalidArgumentException( $m, E_USER_WARNING ); } if( method_exists( [$this, "get{$offset}"] ) ) { return $this->{"get{$offset}"}(); } if( isset( self::PROP[$offset] ) ) { return parent::offsetGet( self::PROP[$offset] ); } $m = "no readable property [{$offset}]"; throw new \UnderflowException( $m, E_USER_WARNING ); } /** * @see <http://php.net/ArrayAccess.offsetSet> * * @throws DomainException if validation fails * @throws OverflowException if offset does not exist or is not settable */ public function offsetSet( $offset, $value ) { $this->offsetValid( $offset, $value, true ); if( method_exists( [$this, "set{$offset}"] ) ) { return $this->{"set{$offset}"}( $value ); } if( isset( self::PROP[$offset] ) ) { return parent::offsetSet( self::PROP[$offset], $value ); } $m = "no setable property [{$offset}]"; throw new \OverflowException( $m, E_USER_WARNING ); } /** * @see <http://php.net/ArrayAccess.offsetUnset> * * @throws UnderflowException if offset does not exist or is not unsettable */ public function offsetUnset( $offset ) { if( ! is_string( $offset ) ) { $t = gettype( $offset ); $m = "\$offset must be a string, [{$t}] provided"; throw new \InvalidArgumentException( $m, E_USER_WARNING ); } if( method_exists( [$this, "unset{$offset}"] ) ) { $this->{"unset{$offset}"}( $value ); } // props with non-null default values are required (cannot be unset) if( isset( static::PROP[$offset] ) && ! isset( static::DATA[$offset] ) ) { parent::offsetUnset( self::PROP[$offset], $value ); } $m = "no unsetable property [{$offset}]"; throw new \UnderflowException( $m, E_USER_WARNING ); } /** * @see modelableAPI::offsetValid() */ public function offsetValid( string $offset, $value, bool $throw=false ) : bool { if( ! $this->offsetExists( $offset ) ) { $m = "no offset [{$offset}] exists"; throw new \OverflowException( $m, E_USER_WARNING ); } $class = static::TYPE[$offset]; if( (! isset( static::TYPE[$offset] )) || ($value instanceof $class || gettype( $value ) === static::TYPE[$offset]) ) { if( (! method_exists( [$this, "validate{$offset}"] )) || $this->{"validate{$offset}"}( $value ) ) { return true; } } if( $throw ){ $m = "invalid value for property [{$offset}]"; throw new \DomainException( $m, E_USER_NOTICE ); } return false; } /** * @see <http://php.net/Iterator.rewind> */ public function rewind() { reset( $this->_enum ); } /** * @see <http://php.net/serializable.serialize> */ public function serialize() { return serialize( parent::toArray() ); } /** nope. */ public function setSize( $size ) {} /** * @see modelableAPI::toArray() */ public function toArray() : array { $enumerable = []; foreach( $this->_enum as $prop ) { $enumerable[$prop] = $this->offsetGet( $prop ); } return $enumerable; } /** * @see <http://php.net/serializable.unserialize> */ public function unserialize( $serialized ) { $props = unserialize( $serialized ); if( ! (is_array( $props ) && (count( $props ) === count( static::PROP ))) ) { $m = '$serialized is not valid property data'; throw new \InvalidArgumentException( $m, E_USER_ERROR ); } $this->__construct(); foreach( (array) unserialize( $serialized ) as $index => $value ) { $offset = array_search( $index, static::PROP ); $this->offsetSet( $offset, $value ); } } /** * @see <http://php.net/Iterator.valid> */ public function valid() { return $this->offsetExists( current( $this->_enum ) ); } }
Output for 8.0.0 - 8.0.30, 8.1.0 - 8.1.28, 8.2.0 - 8.2.18, 8.3.0 - 8.3.4, 8.3.6
Fatal error: Uncaught Error: Interface "at\simple\app\api\modelable" not found in /in/CCc5v:38 Stack trace: #0 {main} thrown in /in/CCc5v on line 38
Process exited with code 255.
Output for 8.3.5
Warning: PHP Startup: Unable to load dynamic library 'sodium.so' (tried: /usr/lib/php/8.3.5/modules/sodium.so (libsodium.so.23: cannot open shared object file: No such file or directory), /usr/lib/php/8.3.5/modules/sodium.so.so (/usr/lib/php/8.3.5/modules/sodium.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0 Fatal error: Uncaught Error: Interface "at\simple\app\api\modelable" not found in /in/CCc5v:38 Stack trace: #0 {main} thrown in /in/CCc5v on line 38
Process exited with code 255.
Output for 7.4.0 - 7.4.33
Fatal error: Uncaught Error: Interface 'at\simple\app\api\modelable' not found in /in/CCc5v:38 Stack trace: #0 {main} thrown in /in/CCc5v on line 38
Process exited with code 255.
Output for 7.0.0 - 7.0.20, 7.1.0 - 7.1.33, 7.2.0 - 7.2.33, 7.3.0 - 7.3.33
Warning: Declaration of at\simple\app\DomainModel::fromArray(array $array) should be compatible with SplFixedArray::fromArray($data, $save_indexes = NULL) in /in/CCc5v on line 38 Fatal error: Interface 'at\simple\app\api\modelable' not found in /in/CCc5v on line 38
Process exited with code 255.
Output for 5.6.0 - 5.6.28
Warning: Unsupported declare 'strict_types' in /in/CCc5v on line 9 Parse error: syntax error, unexpected ':', expecting ';' or '{' in /in/CCc5v on line 82
Process exited with code 255.
Output for 5.5.0 - 5.5.38
Warning: Unsupported declare 'strict_types' in /in/CCc5v on line 9 Fatal error: Arrays are not allowed in class constants in /in/CCc5v on line 44
Process exited with code 255.

preferences:
250.47 ms | 401 KiB | 255 Q