3v4l.org

run code in 300+ PHP versions simultaneously
<?php namespace schlaus\schimile; /** * * Schimile is a validation class * */ class schimile { private static $_ruleset = array(); private static $_errorHandler = null; private static $_latestErrors = null; private static $_currentInstance; private $_currentIndex = 0; private $_optional = array(); private $_nextIndex = 0; private $_inputType; private $_not; private $_queue = array(); private $_queueIndex = 0; private $_errors = array(); private $_haltOnError = false; private $_currentValue; private $_currentValidatorAccepts = array("boolean", "integer", "double", "string", "array", "object"); public function __construct($inputType, $index) { $this->_inputType = $inputType; $this->_updateIndex($index); } private function _accept() { $shortForms = array( "arr" => "array", "str" => "string", "bool" => "boolean", "obj" => "object", "int" => "integer", "float" => "double" ); $accepted = func_get_args(); if (empty($accepted)) $accepted = array("bool", "int", "float", "str", "arr", "obj"); if (count($accepted) == 1 && is_string($accepted)) { $accepted = preg_split('/(, |,|\|)/', $accepted, -1, PREG_SPLIT_NO_EMPTY); } elseif (is_array($accepted[0])) { $accepted = $accepted[0]; } foreach ($accepted as &$val) { if (array_key_exists($val, $shortForms)) $val = $shortForms[$val]; } $this->_currentValidatorAccepts = $accepted; } private function _isValidType($var, $accepted) { return in_array(gettype($var), $accepted); } private function _pushToQueue($validator, $nonNegatedMessage, $negatedMessage, $params = array()) { $message = ($this->_not) ? $negatedMessage : $nonNegatedMessage; $this->_queue[$this->_queueIndex][] = array( "validator" => $validator, "message" => $message, "negate" => $this->_not, "inputType" => $this->_inputType, "accepts" => $this->_currentValidatorAccepts, "useIndex" => $this->_currentIndex, "params" => $params ); $this->_accept(); } private function _reset() { $this->_currentIndex = 0; $this->_nextIndex = 0; $this->_queue = array(); $this->_queueIndex = 0; $this->_errors = array(); } public static function assert($ruleset, $input) { if (is_object($ruleset)) { $instance = $ruleset; } elseif (is_string($ruleset) && array_key_exists($ruleset, self::$_ruleset)) { $instance = clone self::$_ruleset[$ruleset]; } else { throw new InvalidArgumentException("Invalid argument provided for schimile::loadRuleset() (Ruleset object or name expected)"); } return $instance->execute($input); } public static function getErrors() { return self::$_latestErrors; } private function _handleErrors() { self::$_latestErrors = $this->_errors; return false; } private function _pushError($item, $message) { $this->_errors[$item][] = $message; } public function execute($input) { foreach ($this->_queue as $index => $testArrays) { foreach ($testArrays as $testNr => $testBlock) { switch ($testBlock['inputType']) { case "input": $value = &$input; break; case "val": if (is_object($input)) { $value =& $input->$testBlock['useIndex']; } else { $value =& $input[$testBlock['useIndex']]; } break; case "key": $value = key($input); break; } $matcher = !$testBlock['negate']; array_unshift($testBlock['params'], $value); if ($this->_isValidType($value, $testBlock['accepts'])) { try { $result = call_user_func_array($testBlock['validator'], $testBlock['params']); if (!is_bool($result)) { $value = $result; $result = true; } } catch (ValidationFailException $e) { $this->_haltOnError = true; $result = null; } } else { throw new InvalidInputTypeException($testBlock['accepts'], $value); } if ($result === $matcher) { //pass } else { //fail $this->_pushError($this->_currentIndex, $testBlock['message']); if ($this->_haltOnError) { break 2; } } } } if (!empty($this->_errors)) { if (is_null(self::$_errorHandler)) return $this->_handleErrors(); else return self::$_errorHandler($this->_errors); } return true; } private function _composite($params) { $not = $this->_not; foreach ($params as $test) { if (isset($test['negate']) && $test['negate']) { $this->isNot(); } else { $this->is(); } $params = (empty($test['params'])) ? array() : $test['params']; call_user_func_array(array($this, $test['test']), $params); } $this->_not = $not; return $this; } public static function registerErrorHandler($fn) { if (is_callable($fn)) { self::$_errorHandler = $fn; } else { throw new InvalidArgumentException("Invalid argument provided for schimile::registerErrorHandler() (Callable expetcer, " . gettype($fn) . " received)."); } } /** * Gets the currently loaded ruleset * @return Array */ public static function getRuleset() { return self::$_ruleset; } public static function loadRuleset($ruleset) { if (is_object($ruleset)) { self::$_ruleset[] = $ruleset; end(self::$_ruleset[]); return key(self::$_ruleset[]); } elseif (is_array($ruleset)) { self::$_ruleset = array_merge(self::$_ruleset, $ruleset); } else { throw new InvalidArgumentException("Invalid argument provided for schimile::loadRuleset() (Array or Object expected, " . gettype($ruleset) . " received)."); } } private static function _init($type, $index = false) { $self = __CLASS__; $self::$_currentInstance = new $self($type, $index); } private function _nextItem($type, $index = false) { $this->_inputType = $type; $this->_queueIndex++; $this->_updateIndex($index); } private function _updateIndex($index) { if ($index === false) { $this->_currentIndex = $this->_nextIndex++; } else { $this->_currentIndex = $index; } } public static function input() { self::_init("input"); return self::$_currentInstance; } public static function val($index = false) { self::_init("val", $index); return self::$_currentInstance; } public function next($index = false) { $this->_updateIndex($index); return $this; } public function arr() { $this->_pushToQueue(function($input) { return is_array($input); }, "{{name}} must be an array", "{{name}} can't be an array"); return $this; } public function top() { $this->_inputType = "input"; $this->_updateIndex(0); return $this; } public function validPer($ruleset) { $this->_pushToQueue(function($input, $ruleset) { $self = __CLASS__; return $self::assert($ruleset, $input); }, "null", "null", array($ruleset)); return $this; } public function is() { $this->_not = false; return $this; } public function isNot() { $this->_not = true; return $this; } public function noneOf() { $rulesets = func_get_args(); $this->_pushToQueue(function($input, $rulesets) { $self = __CLASS__; $status = false; foreach ($rulesets as $ruleset) { $status = ($status || $self::assert($ruleset, $input)); } return !$status; }, "null", "null", array($rulesets)); return $this; } public function allOf() { $rulesets = func_get_args(); $this->_pushToQueue(function($input, $rulesets) { $self = __CLASS__; $status = true; foreach ($rulesets as $ruleset) { $status = ($status && $self::assert($ruleset, $input)); } return $status; }, "null", "null", array($rulesets)); return $this; } public function oneOf() { $rulesets = func_get_args(); $this->_pushToQueue(function($input, $rulesets) { $self = __CLASS__; $status = false; foreach ($rulesets as $ruleset) { $status = ($status || $self::assert($ruleset, $input)); } return $status; }, "null", "null", array($rulesets)); return $this; } public function haltOnFail() { $this->_haltOnError = true; return $this; } public function continueOnFail() { $this->_haltOnError = false; return $this; } public function required() { if ($key = array_search($this->_currentIndex, $this->_optional) !== false) { unset($this->_optional[$key]); } return $this; } public function optional() { $this->_optional[] = $this->_currentIndex; return $this; } public function string() { //$this->_accept("string", $strict); $this->_pushToQueue(function($input) { return is_string($input); }, "{{name}} must be a string", "{{name}} can't be a string"); return $this; } public function int() { $this->_pushToQueue(function($input) { return is_int($input); }, "{{name}} must be an integer", "{{name}} can't be an integer"); return $this; } public function atStart($param) { $this->_pushToQueue(function($input, $param) { return strpos($input, $param) === 0; }, "{{name}} must start with $param", "{{name}} can't start with $param", array($param)); return $this; } public function atEnd($param) { $this->_pushToQueue(function($input, $param) { return substr($haystack, -strlen($needle)) === $needle; }, "{{name}} must end with $param", "{{name}} can't end with $param", array($param)); return $this; } public function contains($param) { $this->_pushToQueue(function($input, $param) { return strpos($input, $param) !== false; }, "{{name}} must start with $param", "{{name}} can't start with $param", array($param)); return $this; } public function like($type, $keepType = true) { $this->_pushToQueue(function($input, $type) { switch($type) { case "float": case "double": $pattern = '/^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/'; break; case "int": case "integer": $pattern = '/^[-+]?[0-9]+$/'; break; default: throw new InvalidInputTypeException("Invalid comparison type provided for schimile->like() operator"); break; } if (preg_match($pattern, $input)) { if ($keepType) return true; if ($type === "float") return (float) $input; return (int) $input; } else { if ($keepType) return false; throw new ValidationFailException(); } }, "{{name}} must be a valid $type", "{{name}} can't be a $type", array($type)); return $this; } public function likeRegex($pattern) { $this->_pushToQueue(function($input, $pattern) { return (bool) preg_match($pattern, $input); }, "{{name}} must match regex $pattern", "{{name}} can't match regex $pattern", array($pattern)); return $this; } public function numeric() { $this->_pushToQueue(function($input) { return is_numeric($input); }, "{{name}} must be numeric", "{{name}} can't be numeric"); return $this; } public function alnum() { $this->_pushToQueue(function($input) { return ctype_alnum($input); }, "{{name}} must consist of only letters and numbers", "{{name}} can't consist of just letters or numbers"); return $this; } public function charList($characters) { $this->_pushToQueue(function($input, $characters) { $incl = array(); $pattern = preg_replace_callback('/([a-z]\-[a-z])|([0-9]\-[0-9])|([A-Z]\-[A-Z])/', function($matches) use (&$incl) { $incl = array_merge($incl, $matches); return ""; }, $characters); $pattern = preg_quote($pattern); $pattern = $pattern . implode("", array_unique($incl)); $pattern = '/^['.$pattern.']+$/'; return (bool) preg_match($pattern, $input); }, "{{name}} can only contain the characters $characters", "{{name}} can't consist entirely of the characters $characters", array($characters)); return $this; } public function lengthBetween($min = 0, $max = null) { $this->_pushToQueue(function($input, $min, $max) { $resultmin = false; $resultmax = false; if (strlen($input) >= $min) $resultmin = true; if ($max === null || strlen($input) <= $max) $resultmax = true; return $resultmin && $resultmax; }, "{{name}} must be between $min and $max characters", "{{name}} can't be between $min and $max characters", array($min, $max)); return $this; } public function email() { $this->_pushToQueue(function($input) { return (bool) preg_match('/^.+@.+\..+$/', $input); }, "{{name}} must be a valid e-mail address", "{{name}} can't be an e-mail address"); return $this; } public function equalTo($comparison, $strict = true) { $this->_pushToQueue(function($input, $comparison, $strict) { if ($strict) { return $input === $comparison; } else { return $input == $comparison; } }, "{{name}} must be equal to $comparison", "{{name}} can't be $comparison", array($comparison, $strict)); return $this; } public function entropyMin($value) { $this->_pushToQueue(function($input, $value) { $h=0; $size = strlen($string); foreach (count_chars($string, 1) as $v) { $p = $v/$size; $h -= $p*log($p)/log(2); } return $h >= $value; }, "{{name}} must be equal to $comparison", "{{name}} can't be $comparison", array($value)); return $this; } }

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.0110.00416.50
8.3.50.0090.01122.77
8.3.40.0040.01118.79
8.3.30.0150.00619.13
8.3.20.0040.00420.39
8.3.10.0090.00023.70
8.3.00.0000.00817.59
8.2.180.0190.00316.50
8.2.170.0090.00622.96
8.2.160.0070.00720.70
8.2.150.0040.00424.18
8.2.140.0050.00324.66
8.2.130.0100.01026.16
8.2.120.0060.00320.89
8.2.110.0100.00022.26
8.2.100.0000.01219.51
8.2.90.0060.00319.22
8.2.80.0030.00617.97
8.2.70.0060.00317.63
8.2.60.0080.00017.92
8.2.50.0060.00318.07
8.2.40.0030.00518.22
8.2.30.0040.00418.07
8.2.20.0000.00817.67
8.2.10.0030.00618.01
8.2.00.0030.00617.63
8.1.280.0070.00725.92
8.1.270.0060.00323.96
8.1.260.0000.00826.35
8.1.250.0000.00828.09
8.1.240.0060.00323.96
8.1.230.0070.00719.26
8.1.220.0040.00417.79
8.1.210.0040.00418.77
8.1.200.0040.00817.48
8.1.190.0000.00817.25
8.1.180.0040.00418.10
8.1.170.0030.00618.62
8.1.160.0060.00322.13
8.1.150.0000.00818.84
8.1.140.0060.00317.55
8.1.130.0040.00417.98
8.1.120.0040.00417.63
8.1.110.0000.01017.43
8.1.100.0030.00617.46
8.1.90.0030.00517.54
8.1.80.0030.00517.48
8.1.70.0030.00517.50
8.1.60.0000.00917.59
8.1.50.0060.00317.56
8.1.40.0040.00417.63
8.1.30.0030.00617.61
8.1.20.0000.00817.71
8.1.10.0060.00317.52
8.1.00.0050.00317.56
8.0.300.0060.00318.77
8.0.290.0000.00816.75
8.0.280.0000.00718.43
8.0.270.0050.00317.33
8.0.260.0000.00717.34
8.0.250.0050.00217.05
8.0.240.0090.00017.08
8.0.230.0040.00416.87
8.0.220.0040.00416.93
8.0.210.0000.00717.02
8.0.200.0030.00317.04
8.0.190.0030.00716.91
8.0.180.0090.00016.89
8.0.170.0030.00616.97
8.0.160.0000.01116.97
8.0.150.0030.00617.03
8.0.140.0050.00316.86
8.0.130.0000.00613.41
8.0.120.0060.00316.97
8.0.110.0040.00416.89
8.0.100.0040.00416.98
8.0.90.0030.00516.86
8.0.80.0040.01716.93
8.0.70.0030.00517.03
8.0.60.0000.00816.92
8.0.50.0040.00416.88
8.0.30.0120.00817.09
8.0.20.0110.01017.40
8.0.10.0030.00616.95
8.0.00.0110.00816.81
7.4.330.0050.00015.00
7.4.320.0060.00016.68
7.4.300.0070.00016.62
7.4.290.0070.00016.48
7.4.280.0030.00516.62
7.4.270.0020.00516.58
7.4.260.0040.00416.56
7.4.250.0000.00716.55
7.4.240.0000.00716.55
7.4.230.0040.00416.68
7.4.220.0060.01616.69
7.4.210.0070.01316.77
7.4.200.0040.00416.68
7.4.160.0110.00616.39
7.4.150.0030.01717.40
7.4.140.0140.00917.86
7.4.130.0090.01116.56
7.4.120.0100.01416.75
7.4.110.0150.00316.57
7.4.100.0130.00616.64
7.4.90.0140.00416.41
7.4.80.0130.01319.39
7.4.70.0110.00716.48
7.4.60.0060.01216.72
7.4.50.0050.00016.67
7.4.40.0140.00316.64
7.4.30.0110.00716.54
7.4.10.0080.01114.93
7.4.00.0120.00715.08
7.3.330.0030.00313.34
7.3.320.0000.00613.30
7.3.310.0040.00416.13
7.3.300.0000.00716.36
7.3.290.0130.00316.43
7.3.280.0060.01116.41
7.3.270.0140.01117.40
7.3.260.0070.01016.62
7.3.250.0110.01016.58
7.3.240.0100.00716.43
7.3.230.0070.01116.46
7.3.210.0150.00316.35
7.3.200.0030.01519.39
7.3.190.0090.01016.38
7.3.180.0110.00516.41
7.3.170.0120.00616.42
7.3.160.0070.01016.55
7.3.130.0120.00914.92
7.3.120.0030.01714.97
7.3.110.0100.00614.73
7.3.100.0090.00614.90
7.3.90.0070.00715.14
7.3.80.0080.00414.59
7.3.70.0070.00715.02
7.3.60.0080.00514.53
7.3.50.0030.00914.52
7.3.40.0000.01314.82
7.3.30.0040.00814.93
7.3.20.0140.00016.50
7.3.10.0000.01216.54
7.3.00.0080.00816.19
7.2.330.0100.01016.71
7.2.320.0110.01116.61
7.2.310.0090.00916.52
7.2.300.0060.01616.51
7.2.290.0090.00916.76
7.2.260.0060.01314.98
7.2.250.0060.01214.93
7.2.240.0030.01314.93
7.2.230.0120.00615.07
7.2.220.0120.00614.98
7.2.210.0030.01414.97
7.2.200.0040.01114.92
7.2.190.0000.00915.20
7.2.180.0060.00614.61
7.2.170.0060.00615.09
7.2.160.0030.00714.80
7.2.150.0090.00316.67
7.2.140.0000.01516.78
7.2.130.0040.01116.93
7.2.120.0000.01516.39
7.2.110.0110.00716.59
7.2.100.0070.01016.65
7.2.90.0060.01016.36
7.2.80.0040.00816.46
7.2.70.0120.00316.80
7.2.60.0000.01916.83
7.2.50.0000.01216.84
7.2.40.0000.01216.82
7.2.30.0100.00716.49
7.2.20.0130.00016.55
7.2.10.0070.01016.53
7.2.00.0240.00717.80
7.1.330.0000.00915.21
7.1.320.0030.01015.53
7.1.310.0030.01015.46
7.1.300.0000.01115.34
7.1.290.0000.01415.66
7.1.280.0070.00315.61
7.1.270.0030.00915.52
7.1.260.0030.01015.59
7.1.250.0040.01415.59
7.1.240.0060.00615.77
7.1.230.0030.00615.57
7.1.220.0030.01515.63
7.1.210.0090.00915.54
7.1.200.0120.00015.58
7.1.190.0030.01015.38
7.1.180.0040.00815.36
7.1.170.0040.00815.52
7.1.160.0040.00815.60
7.1.150.0040.00415.37
7.1.140.0040.01115.41
7.1.130.0000.00915.43
7.1.120.0000.00915.51
7.1.110.0030.01015.78
7.1.100.0020.01216.57
7.1.90.0000.01415.36
7.1.80.0060.00615.45
7.1.70.0030.00916.28
7.1.60.0020.01016.33
7.1.50.0100.01525.15
7.1.40.0070.00715.59
7.1.30.0060.00615.67
7.1.20.0030.01315.66
7.1.10.0070.01015.39
7.1.00.0020.04418.78
7.0.330.0030.01315.21
7.0.320.0090.00615.13
7.0.310.0030.01015.01
7.0.300.0000.00915.24
7.0.290.0000.00815.17
7.0.280.0060.00615.04
7.0.270.0030.00615.28
7.0.260.0040.00815.03
7.0.250.0030.00915.21
7.0.240.0100.00315.38
7.0.230.0040.01115.18
7.0.220.0040.00815.40
7.0.210.0070.00415.22
7.0.200.0030.00815.84
7.0.190.0070.00415.15
7.0.180.0110.00315.23
7.0.170.0070.00315.43
7.0.160.0030.00715.25
7.0.150.0070.01015.04
7.0.140.0020.04418.72
7.0.130.0070.00715.29
7.0.120.0000.01615.21
7.0.110.0070.00715.16
7.0.100.0200.04717.68
7.0.90.0290.04617.59
7.0.80.0270.04517.77
7.0.70.0310.04017.64
7.0.60.0220.04317.60
7.0.50.0280.04317.99
7.0.40.0050.04516.78
7.0.30.0100.04016.72
7.0.20.0030.04616.62
7.0.10.0120.03316.75
7.0.00.0110.04116.65
5.6.400.0070.00714.39
5.6.390.0000.01614.51
5.6.380.0100.01014.20
5.6.370.0090.00914.38
5.6.360.0100.00314.38
5.6.350.0000.01214.39
5.6.340.0060.00814.46
5.6.330.0000.01314.14
5.6.320.0030.01314.27
5.6.310.0100.00714.17
5.6.300.0030.00914.23
5.6.290.0000.01614.09
5.6.280.0050.04317.61
5.6.270.0090.00314.38
5.6.260.0130.00314.05
5.6.250.0120.04017.49
5.6.240.0060.03217.42
5.6.230.0100.04317.44
5.6.220.0080.04217.53
5.6.210.0060.04317.49
5.6.200.0090.03917.64
5.6.190.0070.04317.78
5.6.180.0130.03817.84
5.6.170.0090.03917.72
5.6.160.0130.03317.61
5.6.150.0020.04917.62
5.6.140.0120.03817.84
5.6.130.0130.02717.68
5.6.120.0060.04517.69
5.6.110.0130.04117.77
5.6.100.0060.04517.60
5.6.90.0030.04517.76
5.6.80.0060.04117.44
5.6.70.0080.04117.46
5.6.60.0050.03717.24
5.6.50.0090.04517.16
5.6.40.0050.04317.40
5.6.30.0050.04417.44
5.6.20.0070.03817.24
5.6.10.0030.02917.44
5.6.00.0070.04117.49
5.5.380.0180.03817.42
5.5.370.0080.04317.35
5.5.360.0070.04517.38
5.5.350.0070.04317.32
5.5.340.0070.04317.72
5.5.330.0130.04317.70
5.5.320.0100.04217.53
5.5.310.0050.04417.65
5.5.300.0100.04717.43
5.5.290.0090.04717.66
5.5.280.0080.02917.63
5.5.270.0110.02817.55
5.5.260.0050.04817.56
5.5.250.0070.04517.42
5.5.240.0140.03717.30
5.5.230.0070.02617.17
5.5.220.0060.03817.29
5.5.210.0080.04317.37
5.5.200.0070.04317.13
5.5.190.0070.04317.15
5.5.180.0050.03817.34
5.5.170.0000.00913.96
5.5.160.0050.04317.28
5.5.150.0020.04917.13
5.5.140.0070.04217.10
5.5.130.0110.04217.34
5.5.120.0100.04017.28
5.5.110.0110.03517.30
5.5.100.0100.04017.12
5.5.90.0080.03917.21
5.5.80.0060.04417.12
5.5.70.0060.04117.18
5.5.60.0060.04017.05
5.5.50.0050.03817.21
5.5.40.0070.04417.13
5.5.30.0080.03916.97
5.5.20.0070.04217.21
5.5.10.0080.04317.16
5.5.00.0030.04616.91
5.4.450.0090.04015.30
5.4.440.0020.02415.16
5.4.430.0020.03815.11
5.4.420.0030.03815.31
5.4.410.0000.03314.99
5.4.400.0040.04615.10
5.4.390.0070.04614.93
5.4.380.0020.04514.83
5.4.370.0060.04014.89
5.4.360.0060.03115.00
5.4.350.0090.02314.90
5.4.340.0060.04614.86
5.4.330.0030.00710.91
5.4.320.0030.03014.90
5.4.310.0040.04115.14
5.4.300.0050.04015.07
5.4.290.0070.02614.91
5.4.280.0080.04015.10
5.4.270.0070.02514.90
5.4.260.0020.04415.08
5.4.250.0050.04314.88
5.4.240.0030.04014.90
5.4.230.0030.04215.08
5.4.220.0140.03514.94
5.4.210.0030.04115.08
5.4.200.0030.04114.87
5.4.190.0020.04014.95
5.4.180.0040.04514.99
5.4.170.0060.02915.10
5.4.160.0000.04314.91
5.4.150.0050.03714.89
5.4.140.0050.04013.66
5.4.130.0080.02313.83
5.4.120.0050.04213.69
5.4.110.0090.03913.75
5.4.100.0070.02613.68
5.4.90.0020.04513.73
5.4.80.0040.03913.65
5.4.70.0030.02213.75
5.4.60.0070.01813.63
5.4.50.0050.02313.79
5.4.40.0100.03513.76
5.4.30.0050.04113.67
5.4.20.0030.04413.71
5.4.10.0090.03613.71
5.4.00.0050.04113.42

preferences:
118.88 ms | 401 KiB | 5 Q