3v4l.org

run code in 300+ PHP versions simultaneously
<?php class TestingAccessWrapper { /** @var mixed The object, or the class name for static-only access */ public $object; /** * Return a proxy object which can be used the same way as the original, * except that access restrictions can be ignored (protected and private methods and properties * are available for any caller). * @param object $object * @return TestingAccessWrapper * @throws InvalidArgumentException */ public static function newFromObject( $object ) { if ( !is_object( $object ) ) { throw new InvalidArgumentException( __METHOD__ . ' must be called with an object' ); } $wrapper = new TestingAccessWrapper(); $wrapper->object = $object; return $wrapper; } /** * Allow access to non-public static methods and properties of the class. * Returns an object whose methods/properties will correspond to the * static methods/properties of the given class. * @param string $className * @return TestingAccessWrapper * @throws InvalidArgumentException */ public static function newFromClass( $className ) { if ( !is_string( $className ) ) { throw new InvalidArgumentException( __METHOD__ . ' must be called with a class name' ); } $wrapper = new TestingAccessWrapper(); $wrapper->object = $className; return $wrapper; } public function __call( $method, $args ) { $methodReflection = $this->getMethod( $method ); if ( $this->isStatic() && !$methodReflection->isStatic() ) { throw new DomainException( __METHOD__ . ': Cannot call non-static method when wrapping static class' ); } return $methodReflection->invokeArgs( $methodReflection->isStatic() ? null : $this->object, $args ); } public function __set( $name, $value ) { $propertyReflection = $this->getProperty( $name ); if ( $this->isStatic() && !$propertyReflection->isStatic() ) { throw new DomainException( __METHOD__ . ': Cannot set non-static property when wrapping static class' ); } $propertyReflection->setValue( $this->object, $value ); } public function __get( $name ) { $propertyReflection = $this->getProperty( $name ); if ( $this->isStatic() && !$propertyReflection->isStatic() ) { throw new DomainException( __METHOD__ . ': Cannot get non-static property when wrapping static class' ); } return $propertyReflection->getValue( $this->object ); } /** * Tells whether this object was created for an object or a class. * @return bool */ private function isStatic() { return is_string( $this->object ); } /** * Return a method and make it accessible. * @param string $name * @return ReflectionMethod */ private function getMethod( $name ) { $classReflection = new ReflectionClass( $this->object ); $methodReflection = $classReflection->getMethod( $name ); $methodReflection->setAccessible( true ); return $methodReflection; } /** * Return a property and make it accessible. * * ReflectionClass::getProperty() fails if the private property is defined * in a parent class. This works more like ReflectionClass::getMethod(). * * @param string $name * @return ReflectionProperty * @throws ReflectionException */ private function getProperty( $name ) { $classReflection = new ReflectionClass( $this->object ); try { $propertyReflection = $classReflection->getProperty( $name ); } catch ( ReflectionException $ex ) { while ( true ) { $classReflection = $classReflection->getParentClass(); if ( !$classReflection ) { throw $ex; } try { $propertyReflection = $classReflection->getProperty( $name ); } catch ( ReflectionException $ex2 ) { continue; } if ( $propertyReflection->isPrivate() ) { break; } else { // @codeCoverageIgnoreStart throw $ex; // @codeCoverageIgnoreEnd } } } $propertyReflection->setAccessible( true ); return $propertyReflection; } } class A { private static function func( &$ref ) { $ref = 42; } } $a = TestingAccessWrapper::newFromClass( A::class ); $b = 0; $a->func( $b ); $a->func( &$b ); echo $b;

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.0.80.0030.01216.81
8.0.70.0150.00916.82
8.0.60.0200.00316.84
8.0.50.0100.01316.75
8.0.30.0120.01816.88
8.0.20.0200.00816.82
8.0.10.0220.00316.93
8.0.00.0070.01016.96
7.4.210.0060.01916.39
7.4.200.0130.01016.43
7.4.190.0170.00616.48
7.4.180.0210.00816.52
7.4.160.0590.01116.30
7.4.150.0260.00616.41
7.4.140.0000.02316.31
7.4.130.0160.00616.09
7.4.120.0110.01416.31
7.4.110.0210.00216.32
7.4.100.0040.01816.25
7.4.90.0190.00416.38
7.4.80.0190.00516.33
7.4.70.0140.00916.16
7.4.60.0120.01016.20
7.4.50.0130.01316.16
7.4.40.0110.01416.27
7.4.30.0420.00516.31
7.4.20.0110.01116.09
7.4.10.0130.01016.27
7.4.00.0160.00616.12
7.3.290.0180.00616.10
7.3.280.0160.00716.11
7.3.270.0150.01516.30
7.3.260.0040.01916.11
7.3.250.0150.00816.11
7.3.240.0310.01416.30
7.3.230.0110.01216.14
7.3.220.0180.00616.05
7.3.210.0160.01216.09
7.3.200.0270.00316.09
7.3.190.0160.01216.24
7.3.180.0220.00716.23
7.3.170.0180.01116.16
7.3.160.0160.01116.14
7.3.150.0170.00716.04
7.3.140.0170.00816.15
7.3.130.0170.01016.05
7.3.120.0300.01316.03
7.3.110.0120.01216.02
7.3.100.0150.00716.05
7.3.90.0130.00916.23
7.3.80.0110.01116.05
7.3.70.0130.00916.22
7.3.60.0170.00616.27
7.3.50.0200.00816.24
7.3.40.0110.01516.27
7.3.30.0230.00316.18
7.3.20.0160.00716.18
7.3.10.0360.00716.09
7.3.00.0140.00916.21

preferences:
146.23 ms | 1394 KiB | 7 Q