3v4l.org

run code in 300+ PHP versions simultaneously
<?php /** * Example of dynamic property that is initialized only when the property is invoked, * i.e. only on get. */ class DynamicPropInitOnGet { public $prop1; public $prop2; public $prop3; public function __construct( $props ) { foreach ( $props as $prop => $value ) { $this->$prop = $value; } } public function __get( $key ) { switch ( $key ) { case 'known': $known = new stdClass(); foreach ( array( 'prop1', 'prop2' ) as $column ) { $known->{$column} = isset( $this->{$column} ) ? $this->{$column} : null; } return $known; } } } class TestMagicMethods { private $obj; private $is_known_prop = false; public function __construct( $obj ) { $this->obj = $obj; } public function test( $prop ) { $this->is_known_prop = ( 'known' === $prop ); // __isset. $this->test_isset( $prop ); // __get(). $this->test_get( $prop ); // __isset() after __get(). $this->test_isset( $prop, true ); // __unset(). $this->test_unset( $prop ); } private function test_isset( $prop, $after_get = false ) { $actual = isset( $this->obj->$prop ); if ( ! $after_get ) { printf( "__isset() results should be false %s\n", $this->test_results( false === $actual ) ); } else { $expected = $this->is_known_prop; printf( "\n\n__isset() after __get() results should be %s %s\n", $this->is_known_prop ? 'true' : 'false', $this->test_results( $expected == $actual ) ); } var_dump( $actual ); } private function test_get( $prop ) { $actual = $this->obj->$prop; $message = "\n\n__get() results should be %s %s\n"; if ( $this->is_known_prop ) { printf( $message, 'an object with prop1 and prop2', $this->test_results( $actual instanceof stdClass ) ); } else { printf( $message, 'null', $this->test_results( null === $actual ) ); } var_dump( $actual ); } private function test_set( $prop ) { $value = $this->is_known_prop ? (array) $this->$obj->known : 'I am an unknown dynamic property'; $obj->$prop = $value; $actual = $this->obj->$prop; if ( $this->is_known_prop ) { printf( "\n\n" . '__set() results should set the value %s and not throw a deprecation on PHP 8.2+.' . 'However, once the __get() is called again, it will set reset it to an object with prop1 and prop2.' . "\n", $this->test_results( $actual instanceof stdClass ) ); } else { printf( "\n\n" . '__set() results should set the value %s and not throw a deprecation on PHP 8.2+.' . 'The set value should remain set when invoking __get()' . "\n", $this->test_results( $value === $actual ) ); } var_dump( $actual ); } private function test_unset( $prop ) {// unset. unset( $this->obj->$prop ); $actual = $this->obj->$prop; $message = "\n\n__unset() + __get() results should be %s %s\n"; if ( $this->is_known_prop ) { printf( $message, 're-init the object with prop1 and prop2', $this->test_results( $actual instanceof stdClass ) ); } else { printf( $message, 'null', $this->test_results( null === $actual ) ); } var_dump( $actual ); } private function test_results( $actual ) { return $actual ? '✅' : '❌'; } } $obj = new DynamicPropInitOnGet( array( 'prop1' => 'foo', 'prop2' => 'bar', 'prop3' => 'baz', ) ); $tester = new TestMagicMethods( $obj ); echo "***** Test the 'known' property *****\n\n"; $tester->test( 'known' ); echo "\n\n***** Unknown, unexpected dynamic property *****\n\n"; $tester->test( 'unknown' );

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)
8.4.10.0080.00019.48
8.3.140.0110.00420.71
8.3.130.0060.00318.24
8.3.120.0000.01019.10
8.3.110.0080.00020.94
8.3.100.0090.00024.06
8.3.90.0040.01126.77
8.3.80.0040.00416.63
8.3.70.0100.00718.30
8.3.60.0110.00716.67
8.3.50.0180.00416.81
8.3.40.0030.02019.84
8.3.30.0100.01319.05
8.3.20.0110.01121.73
8.3.10.0190.00321.90
8.3.00.0070.01518.99
8.2.250.0150.00318.45
8.2.240.0000.00917.46
8.2.230.0080.00022.58
8.2.220.0040.00837.54
8.2.210.0060.00326.77
8.2.200.0060.00316.75
8.2.190.0130.01016.75
8.2.180.0120.00916.63
8.2.170.0100.01318.94
8.2.160.0000.01619.97
8.2.150.0070.01419.06
8.2.140.0120.00920.56
8.2.130.0110.01120.39
8.2.120.0070.01119.27
8.2.110.0090.00619.31
8.2.100.0180.00419.14
8.2.90.0150.00618.96
8.2.80.0100.01019.44
8.2.70.0130.00618.63
8.2.60.0080.00818.85
8.2.50.0120.00319.31
8.2.40.0040.01218.82
8.2.30.0070.01318.84
8.2.20.0130.00618.78
8.2.10.0130.00318.70
8.2.00.0070.01118.83
8.1.300.0070.01119.54
8.1.290.0030.00618.88
8.1.280.0070.01425.92
8.1.270.0090.00622.07
8.1.260.0060.01321.84
8.1.250.0150.00422.13
8.1.240.0060.01018.48
8.1.230.0100.01018.62
8.1.220.0120.00919.07
8.1.210.0120.00418.57
8.1.200.0090.00618.66
8.1.190.0170.00018.65
8.1.180.0040.01518.38
8.1.170.0140.00418.82
8.1.160.0100.00618.35
8.1.150.0040.01118.87
8.1.140.0000.01518.76
8.1.130.0090.00618.86
8.1.120.0060.00918.52
8.1.110.0120.00318.58
8.1.100.0090.00619.74
8.1.90.0110.00418.68
8.1.80.0090.00619.73
8.1.70.0120.00318.80
8.1.60.0110.00418.75
8.1.50.0150.00018.63
8.1.40.0110.00418.81
8.1.30.0070.00719.04
8.1.20.0090.00620.11
8.1.10.0060.00918.60
8.1.00.0000.01518.43

preferences:
25.58 ms | 403 KiB | 5 Q