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( $data, $save_indexes=null ) { 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 ); } $type = static::TYPE[$offset] ?? null; if( (! $type) || ($value instanceof $type || gettype( $value ) === $type) ) { 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 ) ); } }

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
7.0.00.0100.03720.30
5.6.160.0030.04320.54
5.6.150.0030.05018.18
5.6.140.0130.06018.18
5.6.130.0100.05318.27
5.6.120.0070.04321.01
5.6.110.0030.04321.10
5.6.100.0100.08021.02
5.6.90.0100.05320.99
5.6.80.0170.06020.54
5.5.300.0100.07717.99
5.5.290.0100.05717.98
5.5.280.0100.08320.80
5.5.270.0070.08720.86
5.5.260.0030.04020.75
5.5.250.0100.07320.68
5.5.240.0130.08020.36

preferences:
140.45 ms | 1394 KiB | 7 Q