3v4l.org

run code in 300+ PHP versions simultaneously
<?php error_reporting(E_ALL); class DtoException extends Exception { } abstract class Dto { private static $propertyNamesByClass = array(); private function __construct(array $propertiesKeyValues) { foreach($propertiesKeyValues as $propertyName=>$propertyValue) if(Static::hasPropertyName($propertyName)) $this->set($propertyName,$propertyValue); } public function __call($method, array $arguments) { $getOrSet = substr($method, 0, 3); if($getOrSet != 'get' && $getOrSet != 'set') throw new DtoException('"'.get_class($this).'" has no method "'.$method.'"'); $propertyName = strtolower(substr($method, 3)); if(!Static::hasPropertyName($propertyName)) throw new DtoException('"'.get_class($this).'" has no property "'.$propertyName.'"'); $getOrSetMethod = array($this,$getOrSet); array_unshift($arguments,$propertyName); return call_user_func_array($getOrSetMethod, $arguments); } public function __get($propertyName) { if(!Static::hasPropertyName($propertyName)) throw new DtoException('"'.get_class($this).'" has no property "'.$propertyName.'"'); return $this->get($propertyName); } public function __set($propertyName, $propertyValue) { if(!Static::hasPropertyName($propertyName)) throw new DtoException('"'.get_class($this).'" has no property "'.$propertyName.'"'); return $this->set($propertyName, $propertyValue); } public static function createFromArray($propertiesKeyValues) { return new Static($propertiesKeyValues); } public function set($propertyName, $propertyValue) { $this->$propertyName = $propertyValue; } public function get($propertyName) { return $this->$propertyName; } public static function getPropertyNames() { $className = get_called_class(); if(isset(self::$propertyNamesByClass[$className])) return self::$propertyNamesByClass[$className]; $reflected = new ReflectionClass($className); $properties = $reflected->getProperties( ReflectionProperty::IS_PUBLIC ); $propertyNames = array(); foreach($properties as $property) { $propertyNames[] = $property->getName(); } self::$propertyNamesByClass[$className] = $propertyNames; return $propertyNames; } public static function hasPropertyName($propertyName) { $propertyNames = Static::getPropertyNames(); return in_array($propertyName,$propertyNames); } public function asArray() { $values = array(); foreach (Static::getPropertyNames() as $propertyName) { $values[$propertyName] = $this->get($propertyName); } return $values; } public function __sleep() { $propertyNames = self::getPropertyNames(); foreach ($propertyNames as $propertyName) { $propertyValue = $this->get($propertyName); $this->set($propertyName, $propertyValue); } return $propertyNames; } public function __wakeup() { $propertyNames = self::getPropertyNames(); return $propertyNames; } } class Person extends Dto { public $name; public $surname; } class Test { const PERSON_NAME = 'name'; const PERSON_SURNAME = 'surname'; public function testProvideDtoPropertyNames() { $propertyNames = Person::getPropertyNames(); $expectedProperties = array( self::PERSON_NAME, self::PERSON_SURNAME, ); $this->assertEquals( $expectedProperties, $propertyNames ); } public function testProvidePropertyViaGeneralGetter() { $dto = Person::createFromArray(array( self::PERSON_NAME => 'Simone', )); $this->assertEquals( 'Simone', $dto->getName() ); } public function testDTOAcceptOnlyItsOwnProperties() { $dto = Person::createFromArray(array( self::PERSON_NAME => 'Simone', 'non existent property' => 'Simone', )); $expectedProperties = array( self::PERSON_NAME => 'Simone', self::PERSON_SURNAME => null, ); $this->assertEquals( $expectedProperties, $dto->asArray() ); } public function testSerializationKeepSameProperties() { $properties = array( self::PERSON_NAME => 'Simone', self::PERSON_SURNAME => null, ); $dto = Person::createFromArray($properties); $serialized = serialize($dto); $unserialized = unserialize($serialized); $this->assertEquals( $dto->asArray(), $unserialized->asArray() ); $this->assertEquals( $properties, $unserialized->asArray() ); } public function assertEquals($a,$b) { $serializeA = serialize($a); $serializeB = serialize($b); echo ($serializeA==$serializeB?'Pass':'FAIL').' : '.$serializeA.' ; '.$serializeB."\n"; } } $test = new Test(); $test->testProvideDtoPropertyNames(); $test->testProvidePropertyViaGeneralGetter(); $test->testDTOAcceptOnlyItsOwnProperties(); $test->testSerializationKeepSameProperties();
Output for 5.6.0 - 5.6.40, 7.0.12 - 7.0.33, 7.1.0 - 7.1.33, 7.2.0 - 7.2.34, 7.3.0 - 7.3.33, 7.4.0 - 7.4.33, 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
Pass : a:2:{i:0;s:4:"name";i:1;s:7:"surname";} ; a:2:{i:0;s:4:"name";i:1;s:7:"surname";} Pass : s:6:"Simone"; ; s:6:"Simone"; Pass : a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;} ; a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;} Pass : a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;} ; a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;} Pass : a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;} ; a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;}
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 Pass : a:2:{i:0;s:4:"name";i:1;s:7:"surname";} ; a:2:{i:0;s:4:"name";i:1;s:7:"surname";} Pass : s:6:"Simone"; ; s:6:"Simone"; Pass : a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;} ; a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;} Pass : a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;} ; a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;} Pass : a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;} ; a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;}
Output for 7.0.0 - 7.0.11
Pass : a:2:{i:0;s:4:"name";i:1;s:7:"surname";} ; a:2:{i:0;s:4:"name";i:1;s:7:"surname";} Pass : s:6:"Simone"; ; s:6:"Simone"; Pass : a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;} ; a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;} Pass : a:0:{} ; a:0:{} FAIL : a:2:{s:4:"name";s:6:"Simone";s:7:"surname";N;} ; a:0:{}

preferences:
249.31 ms | 402 KiB | 300 Q