3v4l.org

run code in 300+ PHP versions simultaneously
<?php namespace Magnus; class ObjectDispatch { public function routeIterator(&$path) { while (!empty($path)) { yield end($path); array_pop($path); /* This prevents having to put back a value in the event of a * readjustment in the dispatch path. * Testing indicates that it's better to do array maninpulation than it is * to implement SplDoublyLinkedList for deque behavior. Likewise, * simply tracking the index is a bit slower and can add complexity * when dealing with reorients/redispatches. */ } } public function __invoke($context, $root) { $log = $context->logger; $path = $context->getRequestPath(); $last = ''; $parent = null; $current = $root; if ($context->appMode === 'DEBUG' && $log !== null) { $log->addDebug('Starting Object Dispatch', [ 'request' => $context->getRequestURI(), 'path' => var_export($path, true), 'root' => var_export($root, true) ]); } foreach (routeIterator($path) as $chunk) { if ($context->appMode === 'DEBUG' && $log !== null) { $log->addDebug('Beginning dispatch step.', [ 'chunk' => $chunk, 'path' => var_export($path, true), 'current' => var_export($current, true) ]); } if (!is_object($current) || class_exists($context->controllerPrefix . $current)) { if ($context->appMode === 'DEBUG' && $log !== null) { $log->addDebug('Instantiating current class', [ 'request' => $context->getRequestURI(), 'current' => $current ]); } $current = $context->controllerPrefix . $current($context); } if (is_object($current)) { $parent = $current; } if (in_array($chunk, get_class_methods($parent))) { if ($context->appMode === 'DEBUG' && $log !== null) { $log->addDebug('Found an endpoint', [ 'request' => $context->getRequestURI(), 'isEndpoint' => true, 'parent' => var_export($parent, true), 'handler' => $chunk, 'arguments' => var_export($path, true) ]); } yield array($parent, $chunk, $path, true); } elseif (in_array($chunk, get_object_vars($parent))) { if ($context->appMode === 'DEBUG' && $log !== null) { $log->addDebug('Found a property', [ 'request' => $context->getRequestURI(), 'property' => $chunk, 'parent' => var_export($parent, true) ]); } $current = $parent->chunk; } elseif (method_exists($parent, 'lookup')) { try { list($current, $consumed) = $parent->lookup($path); $chunk = implode('/', $consumed); $path = array_slice($path, 0, count($path) - count($consumed)); } catch (Exception $e) { throw new HTTPNotFound(); } } else { throw new HTTPNotFound(); } yield array(explode('/', $last), $parent, false); $last = $chunk; } if ($context->appMode === 'DEBUG' && $log !== null) { $log->addDebug('No endpoint found', [ 'request' => $context->getRequestURI(), 'current' => var_export($current), 'parent' => var_export($parent) ]); } if (!is_object($current) && class_exists($context->controllerPrefix . $current)) { $current = new $context->controllerPrefix . $current($context); } if (is_callable($current)) { yield array($current, $chunk, $path, true); } elseif (is_callable($parent)) { yield array($parent, $chunk, $path, true); } } } class Context { protected $requestURI; protected $requestPath; protected $appMode; protected $logger; protected $controllerPrefix; public function __construct(Array $config) { $this->requestURI = isset($config['requestURI') ? $config['requestURI'] : '/'; $this->requestPath = isset($config['requestPath') ? $config['requestPath'] : array(); $this->appMode = isset($config['appMode') ? $config['appMode'] : 'DEVELOPMENT'; $this->logger = isset($config['logger') ? $config['logger'] : null; $this->controllerPrefix = isset($config['controllerPrefix') ? $config['controllerPrefix'] : null; } public function getRequestURI() { return $this->requestURI; } public function getRequestPath() { if (!is_array($this->requestPath)) { $this->requestPath = explode('/', str_replace('\\', '/', $this->requestURI)); } return $this->requestPath; } } class RootController { public $home = 'homeController'; public function __invoke($args = array()) { return "Root controller index"; } } $context = new Context([ 'requestURI' => '/' ]); $dispatch = new ObjectDispatch(); foreach ($dispatch($context, 'rootController') as $signal) { echo var_export($signal, true) . "\n"; }

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.20.0270.05020.21
7.0.10.0100.08720.26
7.0.00.0030.08320.08
5.6.170.0270.08720.77
5.6.160.0000.07320.44
5.6.150.0100.06318.30
5.6.140.0130.07318.21
5.6.130.0030.08018.23
5.6.120.0030.04321.17
5.6.110.0170.07320.96
5.6.100.0070.05721.05
5.6.90.0070.08721.01
5.6.80.0030.04020.41
5.5.310.0370.07020.53
5.5.300.0230.06318.09
5.5.290.0100.04018.02
5.5.280.0070.08320.95
5.5.270.0100.07020.77
5.5.260.0100.09020.92
5.5.250.0100.07720.66
5.5.240.0070.08320.28

preferences:
159.93 ms | 1398 KiB | 8 Q