3v4l.org

run code in 300+ PHP versions simultaneously
<?php /** * @package at.exceptable * @author Adrian <adrian@enspi.red> * @copyright 2014 - 2016 * @license GPL-3.0 (only) * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License, version 3. * The right to apply the terms of later versions of the GPL is RESERVED. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program. * If not, see <http://www.gnu.org/licenses/gpl-3.0.txt>. */ declare(strict_types = 1); namespace at\exceptable; use ErrorException, Throwable; class Handler { /** @type _Handler[] list of registered error handlers. */ private $_errorHandlers = []; /** @type _Handler[] list of registered exception handlers. */ private $_exceptionHandlers = []; /** @type _Handler[] list of registered shutdown handlers. */ private $_shutdownHandlers = []; /** @type bool is this Handler currently registered (active)? */ private $_registered = false; /** @type int error types which should be thrown as ErrorExceptions. */ private $_throw = 0; /** * registers this handler to invoke a callback, and then restores the previous handler(s). * * @param callable $callback the callback to execute * @param mixed …$arguments arguments to pass to the callback * @return mixed the value returned from the callback */ public function during(callable $callback, ...$arguments) { $this->register(); $value = $callback(...$arguments); $this->unregister(); return $value; } /** * adds an error handler. * @see <http://php.net/set_error_handler> $error_handler * * @param callable $handler the error handler to add * @param int $severity the error severity to trigger this handler * (one of the E_* constants, or omit for "any severity") * @return Handler $this */ public function onError(callable $handler, int $severity=null) : Handler { $this->_errorHandlers[] = new _Handler($handler, _Handler::TYPE_ERROR, $severity); return $this; } /** * adds an exception handler. * @see <http://php.net/set_exception_handler> $exception_handler * * @param callable $handler the exception handler to add * @param int $severity the exception severity to trigger this handler * (one of Exceptable::ERROR|WARNING|NOTICE, or omit for "any severity") * @return Handler $this */ public function onException(callable $handler, int $severity=null) : Handler { $this->_exceptionHandlers[] = new _Handler($handler, _Handler::TYPE_EXCEPTION, $severity); return $this; } /** * adds a shutdown handler. * @see <http:/php.net/register_shutdown_handler> $callback * * @param callable $handler the shutdown handler to add * @param mixed $arguments optional agrs to pass to shutdown handler when invoked * @return Handler $this */ public function onShutdown(callable $handler, ...$arguments) : Handler { $this->_shutdownHandlers[] = (new _Handler($handler, _Handler::TYPE_SHUTDOWN)) ->defaultArguments($arguments); return $this; } /** * registers this Handler's error, exception, and shutdown handlers. * * @return Handler $this */ public function register() : Handler { set_error_handler(function(...$args) { return $this->_error(...$args); }); set_exception_handler(function(...$args) { return $this->_exception(...$args); }); register_shutdown_function(function(...$args) { return $this->_shutdown(...$args); }); $this->_registered = true; return $this; } /** * specifies the ErrorException class for this handler to use. * @todo keep this? * * @param string $fqcn fully qualified ErrorException classname * @return Handler $this */ public function setErrorExceptionClass(string $fqcn) : Handler { throw new ExceptableException('not yet implemented'); } /** * sets error types which should be thrown as ErrorExceptions. * * @param int $severity the error types to be thrown * (defaults to Errors and Warnings; use 0 to stop throwing) * @return Handler $this */ public function throw(int $severity=E_ERROR|E_WARNING) : Handler { $this->_throw = $severity; return $this; } /** * un-registers this Handler. * * @return Handler $this */ public function unregister() : Handler { restore_error_handler(); restore_exception_handler(); // shutdown functions can't be unregistered; just have to flag them so they're non-ops :( $this->_registered = false; return $this; } /** * handles php errors. * * @param int $s error severity * @param string $m error message * @param string $f error file * @param int $l error line * @param array $c error context * @throws ErrorException if error severity matches $_throw setting * @return bool true if error handled; false if php's error handler should continue */ protected function _error(int $s, string $m, string $f, int $l, array $c) : bool { if (! $this->_registered) { return false; } if (($s & $this->_throw) === $s) { throw new ErrorException($m, 0, $s, $f, $l); } foreach ($this->_errorHandlers as $handler) { if ($handler->handles(_Handler::TYPE_ERROR, $s) && $handler->handle($s, $m, $f, $l, $c)) { return true; } } return false; } /** * handles uncaught exceptions. * * @param Throwable $e the exception * @throws ExceptableException if no registered handler handles the exception */ protected function _exception(Throwable $e) { if (! $this->_registered) { return; } $severity = method_exists($e, 'getSeverity') ? $e->getSeverity() : Exceptable::ERROR; foreach ($this->_exceptionHandlers as $handler) { if ($handler->handles(_Handler::TYPE_EXCEPTION, $severity) && $handler->handle($e)) { return; } } throw new ExceptableException(ExceptableException::UNCAUGHT_EXCEPTION, $e); } /** * handles shutdown sequence. * * @throws ErrorException if shutdown is due to a fatal error */ protected function _shutdown() { if (! $this->_registered) { return; } $e = error_get_last(); if ($e && $e['type'] === E_ERROR) { throw new ErrorException($e['message'], 0, $e['type'], $e['file'], $e['line']); } foreach ($this->_shutdownHandlers as $handler) { $handler(); } } } /** @internal utility class for wrapping callables as error/exception/shutdown handlers. */ class _Handler { const TYPE_ERROR = 1; const TYPE_EXCEPTION = 2; const TYPE_SHUTDOWN = 3; const ANY_SEVERITY = -1; protected $_arguments = []; protected $_handler; protected $_type; protected $_severity; public function __construct(callable $handler, int $type, int $severity=null) { $this->_handler = $handler; $this->_type = $type; $this->_severity = $severity ?? self::ANY_SEVERITY; } /** @internal invokes the callback with given arguments. */ public function handle(...$arguments) : bool { try { return ($this->_handler)(...($arguments + $this->_arguments)); } catch (Throwable $e) { throw new ExceptableException( ExceptableException::INVALID_HANDLER, ['type' => $this->_type()], $e ); } } /** @internal checks whether this handler is registered for the given severity. */ public function handles(int $type, int $severity) : bool { return $type === $this->_type && ($this->_severity === self::ANY_SEVERITY || ($severity && $this->_severity) === $severity); } /** @internal specifies default arguments to pass to handler. */ public function defaultArguments(array $arguments) { $this->_arguments = $arguments; return $this; } /** @internal gets a string representation of the handler type. */ protected function _type() : string { switch ($this->_type) { case self::TYPE_ERROR : return 'error'; case self::TYPE_EXCEPTION : return 'exception'; case self::TYPE_SHUTDOWN : return 'shutdown'; default : return (string) $this->_type; } } } interface Exceptable extends \Throwable { /** * exception severity levels. * * @type int ERROR error * @type int WARNING warning * @type int NOTICE notice */ const ERROR = E_ERROR; const WARNING = E_WARNING; const NOTICE = E_NOTICE; /** * default info for unknown/generic exception cases. * * @type int DEFAULT_CODE * @type int DEFAULT_MESSAGE * @type int DEFAULT_SEVERITY */ const DEFAULT_CODE = 0; const DEFAULT_MESSAGE = 'unknown error.'; const DEFAULT_SEVERITY = self::ERROR; /** * gets information about a code known to the implementing class. * * @param int $code the exception code to look up * @throws UnderflowException if the code is not known to the implementation * @return array a map of info about the code, * including (at a minimum) its "code", "severity", and "message". */ public static function get_info(int $code) : array; /** * checks whether the implementation has info about the given code. * * @param int $code the code to check * @return bool true if the code is known; false otherwise */ public static function has_info(int $code) : bool; /** * @param string $0 exception message * if omitted, a message must be set based on the exception code * @param int $1 exception code * if omitted, a default code must be set * @param Throwable $2 previous exception * @param array $3 additional exception context * @throws ExceptableException if argument(s) are invalid */ public function __construct(...$args); /** * adds contextual info to this exception. * * @param array $context map of info to add * @return $this */ public function addContext(array $context) : Exceptable; /** * gets contextual info about this exception. * * @return array map of contextual info about this exception */ public function getContext() : array; /** * traverses the chain of previous exception(s) and gets the root exception. * * @return Throwable the root exception */ public function getRoot() : \Throwable; /** * gets exception severity. * * @return int the exception severity */ public function getSeverity() : int; /** * checks the exception severity. * * @return bool true if exception severity is "Error"; false otherwise */ public function isError() : bool; /** * checks the exception severity. * * @return bool true if exception severity is "Warning"; false otherwise */ public function isWarning() : bool; /** * checks the exception severity. * * @return bool true if exception severity is "Notice"; false otherwise */ public function isNotice() : bool; /** * adds contextual info to this exception. * * @param int $severity one of Exceptable::ERROR|WARNING|NOTICE * @throws ExceptableException if severity is invalid * @return $this */ public function setSeverity(int $severity) : Exceptable; } class ExceptableException extends Exception { /** * @type int NO_SUCH_CODE invalid exception code. * @type int INVALID_CONSTRUCT_ARGS invalid/out-of-order constructor arguments. * @type int INVALID_SEVERITY invalid severity level. * @type int UNCAUGHT_EXCEPTION uncaught/unhandled exception during runtime. * @type int INVALID_HANDLER invalid handler (e.g., wrong signature, or throws). */ const NO_SUCH_CODE = 1; const INVALID_CONSTRUCT_ARGS = (1<<1); const INVALID_SEVERITY = (1<<2); const UNCAUGHT_EXCEPTION = (1<<3); const INVALID_HANDLER = (1<<4); /** @see Exceptable::INFO */ const INFO = [ self::NO_SUCH_CODE => [ 'message' => 'no such code', 'severity' => Exceptable::WARNING, 'tr_message' => "no exception code '{code}' is known" ], self::INVALID_CONSTRUCT_ARGS => [ 'message' => 'constructor arguments are invalid and/or out of order', 'severity' => Exceptable::ERROR, 'tr_message' => "constructor arguments are invalid and/or out of order: {args}" ], self::INVALID_SEVERITY => [ 'message' => 'invalid severity', 'severity' => Exceptable::WARNING, 'tr_message' => 'severity must be one of Exceptable::ERROR|WARNING|NOTICE; {severity} provided' ], self::UNCAUGHT_EXCEPTION => [ 'message' => 'uncaught exception', 'severity' => Exceptable::ERROR, 'tr_message' => 'no registered handler caught exception: {__rootMessage__}' ], self::INVALID_HANDLER => [ 'message' => 'invalid handler', 'severity' => Exceptable::ERROR, 'tr_message' => 'invalid handler [{type}]: {__rootMessage__}' ] ]; } $handler = new Handler(); $handler->onError(function($s, $m, $f, $l, $c) { error_log($m); }) ->register(); trigger_error('foo!', E_USER_NOTICE);

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.3.60.0180.00418.56
8.3.50.0070.01419.93
8.3.40.0070.01118.85
8.3.30.0000.01518.94
8.3.20.0070.00023.65
8.3.10.0000.00823.65
8.3.00.0030.00620.59
8.2.180.0070.01418.18
8.2.170.0000.01522.96
8.2.160.0100.00720.41
8.2.150.0050.00324.18
8.2.140.0060.00324.66
8.2.130.0040.00419.72
8.2.120.0050.00326.35
8.2.110.0060.00322.23
8.2.100.0100.00617.86
8.2.90.0040.00719.20
8.2.80.0000.00817.97
8.2.70.0080.00017.75
8.2.60.0070.00318.16
8.2.50.0030.00518.07
8.2.40.0080.00018.35
8.2.30.0030.00618.12
8.2.20.0040.00418.18
8.2.10.0000.00818.13
8.2.00.0040.00417.75
8.1.280.0060.01525.92
8.1.270.0050.00322.10
8.1.260.0000.00826.35
8.1.250.0040.00428.09
8.1.240.0000.00922.23
8.1.230.0090.00322.29
8.1.220.0060.00317.77
8.1.210.0000.00818.77
8.1.200.0000.01017.48
8.1.190.0000.00817.35
8.1.180.0030.00618.10
8.1.170.0040.00418.61
8.1.160.0060.00318.90
8.1.150.0040.00420.27
8.1.140.0030.00519.65
8.1.130.0030.00319.00
8.1.120.0070.00017.53
8.1.110.0050.00317.56
8.1.100.0040.00417.52
8.1.90.0000.00717.40
8.1.80.0050.00217.43
8.1.70.0000.00817.57
8.1.60.0080.00417.72
8.1.50.0030.00617.54
8.1.40.0030.00617.51
8.1.30.0000.00817.69
8.1.20.0050.00317.72
8.1.10.0040.00417.62
8.1.00.0040.00417.58
8.0.300.0030.00618.77
8.0.290.0060.00316.88
8.0.280.0050.00218.58
8.0.270.0000.00817.32
8.0.260.0000.00818.93
8.0.250.0030.00517.11
8.0.240.0040.00417.07
8.0.230.0040.00417.13
8.0.220.0030.00517.10
8.0.210.0040.00417.00
8.0.200.0070.00317.12
8.0.190.0070.00017.19
8.0.180.0040.00417.00
8.0.170.0040.00417.02
8.0.160.0070.00417.13
8.0.150.0040.00417.01
8.0.140.0000.00717.09
8.0.130.0030.00313.49
8.0.120.0040.00417.05
8.0.110.0030.00517.11
8.0.100.0060.00316.89
8.0.90.0070.00017.03
8.0.80.0130.00317.05
8.0.70.0030.00616.96
8.0.60.0000.00816.93
8.0.50.0000.00817.08
8.0.30.0120.00717.03
8.0.20.0100.01117.41
8.0.10.0030.00517.13
8.0.00.0150.00316.98
7.4.330.0050.00015.55
7.4.320.0030.00316.59
7.4.300.0040.00416.65
7.4.290.0030.00316.55
7.4.280.0080.00316.58
7.4.270.0000.00716.70
7.4.260.0030.00616.57
7.4.250.0080.00016.39
7.4.240.0000.00816.69
7.4.230.0040.00416.66
7.4.220.0090.00916.62
7.4.210.0130.00716.60
7.4.200.0080.00016.75
7.4.160.0100.00716.54
7.4.150.0170.00317.40
7.4.140.0100.00817.86
7.4.130.0100.01016.69
7.4.120.0110.01016.64
7.4.110.0090.01216.66
7.4.100.0160.00316.66
7.4.90.0120.00616.61
7.4.80.0130.01019.39
7.4.70.0080.00916.61
7.4.60.0120.00916.56
7.4.50.0040.01116.47
7.4.40.0080.00816.45
7.4.30.0110.00616.64
7.4.00.0080.00815.18
7.3.330.0030.00513.29
7.3.320.0000.00813.30
7.3.310.0030.00316.54
7.3.300.0000.00716.43
7.3.290.0040.00416.30
7.3.280.0100.01016.43
7.3.270.0070.01117.40
7.3.260.0090.01016.57
7.3.250.0110.00916.50
7.3.240.0090.00916.46
7.3.230.0120.00616.68
7.3.210.0070.01116.67
7.3.200.0000.02419.39
7.3.190.0100.01016.70
7.3.180.0100.00716.70
7.3.170.0080.00816.49
7.3.160.0070.01416.34
7.3.120.0030.01414.86
7.3.110.0040.01514.78
7.3.100.0070.01014.67
7.3.90.0090.00314.79
7.3.80.0060.01014.76
7.3.70.0060.00615.03
7.3.60.0040.01115.06
7.3.50.0060.00914.79
7.3.40.0040.00714.68
7.3.30.0110.00414.45
7.3.20.0110.00316.55
7.3.10.0070.00716.75
7.3.00.0080.00816.58
7.2.330.0070.01316.32
7.2.320.0090.00916.61
7.2.310.0150.00316.68
7.2.300.0160.00516.59
7.2.290.0090.00916.60
7.2.250.0030.01814.82
7.2.240.0120.00814.83
7.2.230.0090.00615.24
7.2.220.0050.00515.05
7.2.210.0070.00314.86
7.2.200.0070.00714.89
7.2.190.0030.01314.85
7.2.180.0030.01015.10
7.2.170.0000.01114.92
7.2.60.0040.00816.59
7.1.330.0060.00615.81
7.1.320.0070.00715.78
7.1.310.0040.00815.70
7.1.300.0030.00715.72
7.1.290.0100.00315.37
7.1.280.0100.00315.69
7.1.270.0080.00615.70
7.1.260.0030.00915.84
7.1.200.0000.01215.47
7.1.100.0110.00618.04
7.1.70.0000.00816.73
7.1.60.0080.00417.09
7.1.50.0040.01816.95
7.1.10.0130.08322.19
7.1.00.0100.06322.25
7.0.200.0040.00816.40
7.0.150.0130.06321.96
7.0.140.0170.06021.89
7.0.130.0170.06021.96
7.0.120.0200.05021.75
7.0.110.0200.06721.85
7.0.100.0070.07021.91
7.0.90.0100.06721.87
7.0.80.0170.07021.93
7.0.70.0170.07722.01
7.0.60.0130.07321.95
7.0.50.0100.08721.95
7.0.40.0030.06721.90
7.0.30.0170.05021.86
7.0.20.0170.05321.86
7.0.10.0000.06721.98
7.0.00.0170.05721.88

preferences:
56.3 ms | 401 KiB | 5 Q