PHP 8.0: New ValueError Error Exception
\ValueError is a new Exception type that extends \Exception class, and from PHP 8.0, you will be seeing lots of them! \ValueError exception is thrown when a value encountered is of correct type, but it cannot be used to continue the operation.
What about other exceptions?
PHP already has exceptions such as \InvalidArgumentException, \OutOfRangeException and \LengthException exceptions that convey a more precise error message.
However, exceptions is the keyword here: The new \ValueError exception extends \Error, instead of \Exception. While you can throw \ValueError exceptions in user-land code, PHP core functions will throw \ValueError exceptions except for a few specific cases (such as sprintf() function throwing \ArgumentCountError exceptions instead of the legacy Warning: sprintf(): Too few arguments warning).
Throwable
├── Error
│ ├── TypeError
│ ├── ValueError
│
└── Exception
├── LogicException
├── DomainException
├── InvalidArgumentException
├── LengthException
└── OutOfRangeException
This is a simplified chart of PHP core \Error and \Exception. You can take a look at full PHP Exception hierarchy in this post.
From PHP 8.0 and forward, \ValueError errors will be thrown when the value passed to a function is of a valid type, but is not valid for the operation.
Examples
-
strpos()attempting to set a offset longer than the haystack lengthBefore PHP 8.0:
$a = strpos("s", "small", 16); // Warning: strpos(): Offset not contained in string in ... on line ... var_dump($a); // bool(false)From PHP 8.0
$a = strpos("s", "small", 16); // Uncaught ValueError: Offset not contained in string in ...:...
-
range()with non-positive stepsBefore PHP 8.0:
$a = range(1, 2, 0); // Warning: range(): step exceeds the specified range in ... on line ... var_dump($a); // bool(false)From PHP 8.0
$a = range(1, 2, 0); // Uncaught ValueError: Step exceeds the specified range ...:...
-
array_rand()with an empty arrayBefore PHP 8.0:
$a = array_rand(array(), 0); // Warning: array_rand(): Array is empty in ... on line ... var_dump($a); // NULLFrom PHP 8.0
$a = array_rand(array(), 0); // Uncaught ValueError: Array is empty in ...:...
But why?
The new \ValueError exception is introduced as part of the major change Internal function warnings now throw TypeError and ValueError exceptions, where you can find detailed information.
Polyfill
It is possible to polyfill this exception class by simply declaring a user-land class with the same name.
if (!class_exists('\ValueError')) {
class ValueError extends \Error {
}
}
Note that this will not make internal PHP functions throw \ValueError exceptions when appropriate. However, if you have user-land code that needs to throw \ValueError exceptions, it is now possible with the polyfill.
Backwards compatibility impact
\ValueError is a new class, and unless you have user-land implementations, there should be no BC impact.