InvalidArgumentException vs UnexpectedValueException
I guess the largest difference is "argument" vs "value".
The way I see it is that InvalidArgumentException
is for (passed) arguments, whereas UnexpectedValueException
applies to (returned) values.
Also there's a subtle but important difference between "invalid" and "unexpected" - which also explains why the first is LogicException and the second a RuntimeException.
For example: say i've got a function that utilizes the Twitter-api called: getLastMessageDate($userid)
:
You pass a (numeric) user-id and it returns the date of the last message of that user as yyyy-mm-dd string.
Now, suppose I call this function with a string as argument instead of a number. At this point I can call an InvalidArgumentException, because the provided argument is invalid for this function. These checks can be done by logic - because a variable is either numeric or it is not. Therefore it's a LogicException.
However, the return value of a function may not be verifiable by logic - especially when you're dealing with (third-party) dynamic content. Because you can never know exactly what your function is going to return. (if you would, this would arguably render your function useless.)
So, this time I call my function with a (valid) user-id and my function gets the date of the last message of that user. With this date I would like to do something, like some formatting.
Now imagine the guys at Twitter did something wrong and instead of my expected yyyy-mm-dd date-string, I get an empty string or a different string saying 'blaaaa'.
At this point, i can throw an UnexpectedValueException
.
I can't say that this value is "Invalid" - I asked for a string and I got a string. But it is however not the "kind of string" i was expecting: therefore Unexpected ValueException.
Hope this clears something up. This is my first post - so far I've learned that writing down what's in my head isn't the easiest thing (also English is not my native language).
Looking closely at the descriptions on the manual pages:
InvalidArgumentException
Exception thrown if an argument is not of the expected type.
(The description was Exception thrown if an argument does not match with the expected value.
until mid-2014, but was changed when PHP 5.6 got introduced)
UnexpectedValueException
Exception thrown if a value does not match with a set of values. Typically this happens when a function calls another function and expects the return value to be of a certain type or value[,] not including arithmetic or buffer related errors.
From this, we can conclude that InvalidArgumentException
is intended to check types of arguments passed to a function, while UnexpectedValueException
is intended to verify values vs valid value sets, possibly during the internal computations of a function (e.g. values returned from other functions).
Note that checking the values of arguments is kind of gray area here; arguably, since InvalidArgumentException extends LogicException
, it should only handle situations which should lead directly to a fix in your code.
Since throwing an exception in case of out-of-range input values can be a completely expected runtime behaviour, this leaves UnexpectedValueException
(which extends RuntimeException
) as the only candidate in such cases.
My understanding is that InvalidArgumentException
, being a LogicException
, should be used if you check an argument against a fixed list of possible value ranges. For example, checking if user entered data contains only numbers. The program logic can be expected to handle these value ranges.
UnexpectedValueException
, being a RuntimeException
(errors that can only be found on runtime / cannot be detected at compile time), would be used for Exceptions that occur outside of foreseeable and specified input ranges (possibly as a last resort after the "logic" checks above).
The key to answering this question might be the Unexpected...
in UnexpectedValueException
. Unexpected
means there is no handling for this value in the program logic. Invalid
, on the other hand, suggests that this value has been handled.