3v4l.org

run code in 300+ PHP versions simultaneously
<?php /** * Class URL * * @package HTTP * @property string $scheme * @property string $user * @property string $pass * @property string $host * @property string $port * @property string $path * @property string $fragment */ class URL { /** * @var string */ private $scheme; /** * @var string */ private $user; /** * @var string */ private $pass; /** * @var string */ private $host; /** * @var int */ private $port; /** * @var string */ private $path; /** * @var array|string * * NOTE: do not attempt to validate this on access because it's too difficult to do sensibly */ public $query = []; /** * @var string */ private $fragment; /** * @var string[] */ private static $stringProperties = ['scheme', 'user', 'pass', 'host', 'path', 'fragment']; /** * Wrapper for parse_url() * * @param string $string * @return URL * @throws \InvalidArgumentException */ public static function createFromString($string) { if (false === $parts = parse_url($string)) { throw new \InvalidArgumentException($string . ' could not be parsed as a valid URL'); } return new static( isset($parts['scheme']) ? $parts['scheme'] : null, isset($parts['user']) ? $parts['user'] : null, isset($parts['pass']) ? $parts['pass'] : null, isset($parts['host']) ? $parts['host'] : null, isset($parts['port']) ? $parts['port'] : null, isset($parts['path']) ? $parts['path'] : null, isset($parts['query']) ? $parts['query'] : null, isset($parts['fragment']) ? $parts['fragment'] : null, true ); } /** * Resolve $target as a relative URL against this, using the same rules as a browser * * @param string|URL $target * @return URL */ public function resolve($target) { if (!($target instanceof static)) { $target = static::createFromString((string) $target); } // returning the same instance sometimes but not others would be confusing $result = clone $target; if (!isset($target->scheme)) { // anything with a scheme is considered absolute if (isset($target->host)) { // similarly anything with a host is absolute, just add a scheme is we have one if (isset($this->scheme)) { $result->scheme = $this->scheme; } } else { // host/scheme portion not specified, inherit from source foreach (['scheme', 'user', 'pass', 'host', 'port'] as $prop) { if (isset($this->{$prop})) { $result->{$prop} = $this->{$prop}; } } if ($target->path === '') { $target->path = '/'; } if ($target->path[0] === '/') { // If the target path is absolute, canonicalize it and use it $resultPath = self::resolveCanonicalPathComponents($target->path); } else { // Target path is relative // First we resolve the source path to a canonical and remove the file name component $sourcePath = self::resolveCanonicalPathComponents($this->path); array_pop($sourcePath); // Now resolve the target path against the source $resultPath = self::resolveCanonicalPathComponents($target->path, $sourcePath); } $result->path = '/' . implode('/', $resultPath); // The query and fragment elements are not inheritable so we don't touch them } } return $result; } /** * Normalise a path, resolving empty, . and .. components, optionally against another path * * @param string $path * @param string[] $target * @return string[] */ private static function resolveCanonicalPathComponents($path, array $target = []) { // strip empty components and resolve . and .. foreach (preg_split('#[\\\\/]+#', $path, -1, PREG_SPLIT_NO_EMPTY) as $component) { switch ($component) { case '.': // current directory - do nothing break; case '..': // up a level array_pop($target); break; default: array_push($target, $component); break; } } // add a trailing empty element if path refers to a directory $lastChar = $path[strlen($path) - 1]; if ($lastChar === '/' || $lastChar === '\\') { array_push($target, ''); } return $target; } /** * Replacement for parse_str() because it sucks * * @param string $str * @return array */ private function parseQueryString($str) { $result = []; foreach (explode('&', $str) as $element) { $parts = explode('=', $element, 2); $key = urldecode(array_shift($parts)); $value = $parts ? urldecode(array_shift($parts)) : ''; if (false === $pos = strpos($key, '[')) { $result[$key] = $value; } else { $base = substr($key, 0, $pos++); if (!isset($result[$base]) || !is_array($result[$base])) { $result[$base] = []; } $target = &$result[$base]; $length = strlen($key); do { $end = strpos($key, ']', $pos); $index = substr($key, $pos, $end - $pos); $pos = $end + 1; if (!isset($key[$pos])) { $target[$index] = $value; break; } if ($key[$pos] !== '[') { $target[$index] = [substr($key, $pos) => $value]; break; } if (!isset($target[$index]) || !is_array($target[$index])) { $target[$index] = []; } $target = &$target[$index]; } while(++$pos < $length); } } return $result; } /** * Build a query string from a set of data * * Assume that any scalar data is a query string literal, cast vectors to array and build as form data * * @param mixed $data * @return string */ private function buildQueryString($data) { return is_scalar($data) ? (string) $data : http_build_query((array) $data); } /** * Normalize slashes in a path and URL-encode without encoding slashes * * @param string $path * @return string */ private function urlEncodePath($path) { return implode('/', array_map('urlencode', preg_split('#[\\\\/]+#', $path))); } /** * Set the port number * * @param int $port * @throws \LogicException */ private function setPort($port) { if ($port !== null) { $port = (string) $port; if (!ctype_digit($port)) { // IMPORTANT NOTE: the range of the port is *not* limited to the bounds of any specific integer type // RFC 3896 sec 3.2.3 simply specifies *DIGIT // DO NOT VALIDATE THIS VALUE ANY MORE THAN THIS! throw new \LogicException('Port can only contain digits'); } } $this->port = $port; } /** * Constructor takes URL-encoded components as individual arguments * * @param string $scheme * @param string $user * @param string $pass * @param string $host * @param int $port * @param string $path * @param string|array $query * @param string $fragment */ public function __construct($scheme = null, $user = null, $pass = null, $host = null, $port = null, $path = null, $query = null, $fragment = null) { foreach (self::$stringProperties as $property) { if (${$property} !== null) { $this->{$property} = urldecode((string) ${$property}); } } // This is a special case. We do not attempt to validate any other component as they can contain more // or less anything due to multilingual transformations, but this *must* be all digits at all times $this->setPort($port); if ($query !== null) { $this->query = is_scalar($query) ? $this->parseQueryString($query) : (array) $query; } } /** * Magic getter * * @param string $name * @return mixed */ public function __get($name) { if (isset($this->{$name})) { return $this->{$name}; } trigger_error('Attempt to access unknown property URL::$' . $name, E_USER_NOTICE); return null; } /** * Magic setter * * @param string $name * @param mixed $value */ public function __set($name, $value) { if (in_array($name, self::$stringProperties)) { $this->{$name} = $value !== null ? (string) $value : null; } else if ($name === 'port') { $this->setPort($value); } else { trigger_error('Attempt to access unknown property URL::' . $name, E_USER_NOTICE); } } /** * Forms all non-null components into a URL * * @return string */ public function __toString() { $result = ''; if (isset($this->host)) { if (isset($this->scheme)) { $result = $this->scheme . ':'; } $result .= '//'; if (isset($this->user)) { $result .= urlencode($this->user); if (isset($this->pass)) { $result .= ':' . urlencode($this->pass); } $result .= '@'; } $result .= $this->host; if (isset($this->port)) { $result .= ':' . $this->port; } if (isset($this->path) && !in_array($this->path[0], ['\\', '/'])) { $result .= '/'; } } if (isset($this->path)) { $result .= $this->urlEncodePath($this->path); } if (isset($this->query) && $this->query !== [] && $this->query !== '') { $result .= '?' . $this->buildQueryString($this->query); } if (isset($this->fragment)) { $result .= '#' . urlencode($this->fragment); } return $result; } } $url = URL::createFromString('http://www.google.com/foo+bar/baz?foo=bar#baz'); echo "Path is " . $url->path . "\n"; echo "Rebuilt is " . $url;

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.0190.00318.55
8.3.50.0120.00921.39
8.3.40.0080.00819.07
8.3.30.0110.00420.46
8.3.20.0150.00020.31
8.3.10.0030.00621.95
8.3.00.0030.00622.51
8.2.180.0000.01618.91
8.2.170.0130.00322.96
8.2.160.0080.00820.65
8.2.150.0050.00324.18
8.2.140.0110.00724.66
8.2.130.0090.00926.16
8.2.120.0080.00019.89
8.2.110.0100.00020.50
8.2.100.0040.00818.22
8.2.90.0040.00419.50
8.2.80.0030.00519.34
8.2.70.0030.00618.00
8.2.60.0040.00418.18
8.2.50.0000.01018.07
8.2.40.0050.00318.40
8.2.30.0050.00319.60
8.2.20.0060.00318.13
8.2.10.0030.00618.04
8.2.00.0000.00818.01
8.1.280.0180.00325.92
8.1.270.0130.01020.44
8.1.260.0050.00326.35
8.1.250.0050.00328.09
8.1.240.0070.00322.67
8.1.230.0040.00821.03
8.1.220.0000.00818.77
8.1.210.0070.00319.09
8.1.200.0030.00617.61
8.1.190.0050.00317.64
8.1.180.0030.00618.10
8.1.170.0040.00418.95
8.1.160.0060.00319.16
8.1.150.0040.00418.94
8.1.140.0030.00517.73
8.1.130.0030.00517.98
8.1.120.0040.00417.77
8.1.110.0060.00617.75
8.1.100.0000.00817.74
8.1.90.0000.00817.76
8.1.80.0000.00717.73
8.1.70.0000.00717.65
8.1.60.0060.00317.87
8.1.50.0040.00717.72
8.1.40.0030.00517.69
8.1.30.0030.00517.89
8.1.20.0030.00617.83
8.1.10.0050.00317.75
8.1.00.0060.00317.75
8.0.300.0000.00820.09
8.0.290.0060.00317.29
8.0.280.0050.00218.59
8.0.270.0040.00417.35
8.0.260.0040.00417.10
8.0.250.0000.00717.20
8.0.240.0030.00517.25
8.0.230.0000.00717.30
8.0.220.0040.00417.19
8.0.210.0030.00317.20
8.0.200.0050.00217.26
8.0.190.0030.00617.30
8.0.180.0080.00017.21
8.0.170.0000.00817.21
8.0.160.0030.00517.09
8.0.150.0000.00717.15
8.0.140.0000.00717.18
8.0.130.0030.00313.54
8.0.120.0000.00817.24
8.0.110.0030.00617.15
8.0.100.0000.00717.25
8.0.90.0040.00417.23
8.0.80.0080.00817.17
8.0.70.0000.00817.36
8.0.60.0040.00417.09
8.0.50.0000.00817.30
8.0.30.0070.01217.48
8.0.20.0050.01417.40
8.0.10.0000.01017.27
8.0.00.0100.00917.11
7.4.330.0050.00015.00
7.4.320.0030.00317.04
7.4.300.0030.00317.00
7.4.290.0030.00316.84
7.4.280.0000.00716.90
7.4.270.0070.00016.79
7.4.260.0050.00316.95
7.4.250.0000.00716.86
7.4.240.0010.00616.93
7.4.230.0000.00716.71
7.4.220.0160.01017.02
7.4.210.0080.00717.00
7.4.200.0040.00416.78
7.4.190.0040.00417.06
7.4.160.0100.00616.98
7.4.150.0040.01517.40
7.4.140.0090.01317.86
7.4.130.0120.01016.87
7.4.120.0110.00916.95
7.4.110.0090.00916.66
7.4.100.0060.01816.83
7.4.90.0120.00616.72
7.4.80.0040.01819.39
7.4.70.0100.00716.80
7.4.60.0090.00916.83
7.4.50.0030.00317.00
7.4.40.0030.01222.77
7.4.30.0060.01216.79
7.4.00.0020.01515.29
7.3.330.0000.00513.63
7.3.320.0000.00613.62
7.3.310.0040.00416.59
7.3.300.0030.00316.59
7.3.290.0060.00916.56
7.3.280.0100.00916.61
7.3.270.0070.01117.40
7.3.260.0090.00916.91
7.3.250.0110.00716.76
7.3.240.0060.01816.81
7.3.230.0090.01016.66
7.3.210.0090.00916.89
7.3.200.0100.01319.39
7.3.190.0030.01516.60
7.3.180.0070.01016.82
7.3.170.0070.01116.64
7.3.160.0110.01116.71
7.3.120.0050.01215.19
7.3.110.0090.00915.37
7.3.100.0060.00615.25
7.3.90.0060.00615.17
7.3.80.0040.01115.33
7.3.70.0040.00715.25
7.3.60.0060.00915.26
7.3.50.0120.00315.19
7.3.40.0080.00415.14
7.3.30.0030.01015.00
7.3.20.0110.00317.05
7.3.10.0050.01016.93
7.3.00.0060.00816.69
7.2.330.0100.01017.04
7.2.320.0040.01516.99
7.2.310.0060.01616.99
7.2.300.0030.01916.76
7.2.290.0060.01916.98
7.2.250.0130.00715.53
7.2.240.0080.01215.55
7.2.230.0070.01115.27
7.2.220.0030.00915.44
7.2.210.0060.00615.57
7.2.200.0000.01115.07
7.2.190.0030.01415.27
7.2.180.0090.00615.30
7.2.170.0090.00615.46
7.2.160.0040.01415.59
7.2.150.0040.01517.14
7.2.140.0080.00416.87
7.2.130.0060.01017.32
7.2.120.0100.00516.95
7.2.110.0100.00616.98
7.2.100.0060.00916.91
7.2.90.0070.00717.12
7.2.80.0050.00816.93
7.2.70.0050.00817.06
7.2.60.0050.01017.09
7.2.50.0090.00617.05
7.2.40.0080.00817.13
7.2.30.0050.01016.94
7.2.20.0090.00417.00
7.2.10.0120.00716.90
7.2.00.0110.00517.97
7.1.330.0000.01315.67
7.1.320.0030.01315.95
7.1.310.0060.00615.91
7.1.300.0040.01116.11
7.1.290.0040.00815.89
7.1.280.0040.00415.98
7.1.270.0060.01015.91
7.1.260.0000.01415.85
7.1.250.0020.01315.96
7.1.240.0030.01015.77
7.1.230.0070.00415.98
7.1.220.0100.00315.98
7.1.210.0070.01016.02
7.1.200.0040.01116.17
7.1.190.0090.00415.70
7.1.180.0030.00916.02
7.1.170.0070.00716.07
7.1.160.0070.00415.78
7.1.150.0080.00416.16
7.1.140.0030.01016.05
7.1.130.0040.00815.93
7.1.120.0060.00615.99
7.1.110.0060.00916.09
7.1.100.0060.00717.27
7.1.90.0040.00816.09
7.1.80.0000.01615.73
7.1.70.0060.00616.68
7.1.60.0120.00917.71
7.1.50.0020.01416.58
7.1.40.0110.00015.98
7.1.30.0060.00816.11
7.1.20.0080.00516.04
7.1.10.0000.01416.14
7.1.00.0030.02319.13
7.0.330.0070.01015.43
7.0.320.0060.00615.71
7.0.310.0030.01015.59
7.0.300.0100.00315.37
7.0.290.0040.00415.68
7.0.280.0060.00615.60
7.0.270.0080.00415.62
7.0.260.0040.00715.76
7.0.250.0110.00315.70
7.0.240.0060.00915.57
7.0.230.0060.00615.65
7.0.220.0030.00615.59
7.0.210.0060.00915.68
7.0.200.0150.00615.27
7.0.190.0030.00615.70
7.0.180.0070.00715.64
7.0.170.0040.01115.28
7.0.160.0080.00615.57
7.0.150.0030.00915.87
7.0.140.0050.03918.70
7.0.130.0070.00715.77
7.0.120.0060.01015.77
7.0.110.0130.00015.46
7.0.100.0050.03717.81
7.0.90.0180.03317.87
7.0.80.0100.03017.77
7.0.70.0130.03817.74
7.0.60.0050.03117.87
7.0.50.0130.02518.09
7.0.40.0060.04316.88
7.0.30.0040.03016.95
7.0.20.0050.04616.91
7.0.10.0120.03716.74
7.0.00.0060.03416.90
5.6.400.0000.01114.58
5.6.390.0030.01014.30
5.6.380.0120.00414.57
5.6.370.0090.00614.56
5.6.360.0060.01114.23
5.6.350.0080.00414.57
5.6.340.0030.01014.37
5.6.330.0100.00714.88
5.6.320.0070.00714.77
5.6.310.0120.00314.90
5.6.300.0070.00714.68
5.6.290.0060.00614.48
5.6.280.0050.04017.86
5.6.270.0030.00614.67
5.6.260.0070.01014.66
5.6.250.0070.04917.55
5.6.240.0050.04917.67
5.6.230.0110.03817.58
5.6.220.0070.04317.66
5.6.210.0070.02717.55
5.6.200.0050.04217.65
5.6.190.0100.03217.92
5.6.180.0040.03717.89
5.6.170.0130.04217.85
5.6.160.0020.04917.80
5.6.150.0080.04817.92
5.6.140.0160.03317.92
5.6.130.0070.04817.85
5.6.120.0070.02917.89
5.6.110.0070.04517.83
5.6.100.0100.02917.86
5.6.90.0070.04417.95
5.6.80.0000.05117.53
5.6.70.0050.02317.41
5.6.60.0120.03917.56
5.6.50.0050.02817.55
5.6.40.0100.02717.63
5.6.30.0030.02417.72
5.6.20.0080.03117.43
5.6.10.0070.04517.42
5.6.00.0070.04317.64
5.5.380.0050.04617.74
5.5.370.0090.02317.57
5.5.360.0080.02517.55
5.5.350.0080.03217.58
5.5.340.0100.04217.70
5.5.330.0120.03817.75
5.5.320.0030.04117.79
5.5.310.0010.04717.91
5.5.300.0140.02617.70
5.5.290.0110.04117.55
5.5.280.0050.02717.75
5.5.270.0070.05217.69
5.5.260.0150.03217.74
5.5.250.0050.03517.69
5.5.240.0100.04017.36
5.5.230.0070.02817.36
5.5.220.0090.02217.44
5.5.210.0110.04117.40
5.5.200.0130.03717.29
5.5.190.0050.04517.38
5.5.180.0090.02917.19
5.5.170.0080.00714.64
5.5.160.0030.04717.33
5.5.150.0050.03217.29
5.5.140.0030.04917.29
5.5.130.0030.03617.47
5.5.120.0000.04117.43
5.5.110.0050.04117.34
5.5.100.0130.03317.38
5.5.90.0160.02317.38
5.5.80.0140.03617.32
5.5.70.0050.04817.39
5.5.60.0030.04717.40
5.5.50.0080.03117.38
5.5.40.0050.02817.37
5.5.30.0000.03017.34
5.5.20.0100.03717.40
5.5.10.0140.03517.41
5.5.00.0050.04017.19
5.4.450.0050.04015.27
5.4.440.0050.02915.53
5.4.430.0030.04915.37
5.4.420.0080.03715.35
5.4.410.0100.04215.29
5.4.400.0050.02415.29
5.4.390.0020.04815.23
5.4.380.0030.02915.18
5.4.370.0050.04215.30
5.4.360.0020.04215.14
5.4.350.0050.03515.11
5.4.340.0030.04115.04
5.4.330.0000.00911.29
5.4.320.0070.01715.18
5.4.310.0020.03715.30
5.4.300.0080.03515.28
5.4.290.0080.03815.20
5.4.280.0030.04415.27
5.4.270.0060.03115.29
5.4.260.0080.03615.21
5.4.250.0060.04015.27
5.4.240.0120.03715.27
5.4.230.0090.03815.06
5.4.220.0060.02815.18
5.4.210.0050.04415.12
5.4.200.0020.02914.97
5.4.190.0030.02515.08
5.4.180.0030.03315.15
5.4.170.0030.03915.20
5.4.160.0080.02715.11
5.4.150.0070.04315.15
5.4.140.0070.02013.96
5.4.130.0020.03914.07
5.4.120.0120.03313.85
5.4.110.0040.02413.82
5.4.100.0070.02214.01
5.4.90.0030.03413.81
5.4.80.0020.03513.81
5.4.70.0070.02913.83
5.4.60.0040.02413.79
5.4.50.0050.03013.81
5.4.40.0050.02213.93
5.4.30.0030.03213.94
5.4.20.0050.02613.89
5.4.10.0050.03913.76
5.4.00.0050.02813.70
5.3.290.0040.04512.52
5.3.280.0050.04212.44
5.3.270.0100.03712.32
5.3.260.0020.04112.49
5.3.250.0100.03612.38
5.3.240.0070.02012.49
5.3.230.0130.02812.40
5.3.220.0130.03512.40
5.3.210.0030.02312.47
5.3.200.0060.03512.38
5.3.190.0030.02912.39
5.3.180.0020.02612.35
5.3.170.0040.04112.44
5.3.160.0020.02812.54
5.3.150.0030.02312.35
5.3.140.0040.02112.48
5.3.130.0020.02912.44
5.3.120.0020.02912.44
5.3.110.0030.02612.43
5.3.100.0150.02312.12
5.3.90.0020.03012.23
5.3.80.0080.03312.14
5.3.70.0040.04212.14
5.3.60.0020.03412.04
5.3.50.0070.03512.04
5.3.40.0030.02511.99
5.3.30.0050.04012.03
5.3.20.0050.03711.89
5.3.10.0050.02811.90
5.3.00.0020.02511.83

preferences:
31 ms | 401 KiB | 5 Q