PHP typehinting gotcha in exceptions/methods

Tags:

A small gotcha I recently ran into: If you use typehinting, PHP never checks that the class your typehint specifies actually exists!

Read more for some examples

As you may be aware of, typehints are quite convenient when you want a parameter to be an instance of some specific class or interface:

function sayHello(User $user) {
    echo 'Hello ' . $user->getName();
}

It turns out PHP never checks the class you use in the typehint…

function sayHello(Fasdfasdfasdfasd $user) {
    echo 'Hello ' . $user->getName();
}

This will actually work just fine, until you try to call it – but not because of the typehint, but because you can’t actually create a new instance of it as it doesn’t exist.

This same issue actually also applies to catch-blocks:

catch(ThisDoesNotNeedToExist $ex) { 
}

Worse with namespaces

This trap is a bit easier to fall into in namespaced code, due to the relative nature of namespace lookups in PHP:

namespace MyNamespace;
 
function something() {
    try {
        //Do something
    }
    catch(Exception $ex) {
        //catch something
    }
}

Notice the problem in above code?

If you didn’t, don’t worry – this is the most common error I see people make with namespaces.

The exception class actually being caught in the above code is MyNamespace\Exception. Of course, you would never get an error, because PHP doesn’t check the typehint. All exceptions are just going to fall through the catch-block just like it wasn’t there at all.

Is this really all bad?

In my opinion this is a rather poor “feature”, because one of the point of typehints in my opinion is to ensure validity of code and not checking the typehints does not really help in that at all.

However, while discussing this on #zftalk-community, user “Xerkus” suggested another point of view for the case with exceptions.

He mentioned that sometimes you may have a script which supports different types of libraries, each with their own exception types. If you only have one library installed, the code would fail to function if the exception class name was validated.

While he does have a kind of a valid point, I think it would be a better idea to use an adapter and wrap exceptions instead. It might be convenient in simple scripts that the class name isn’t validated, but I think overall it only causes more error-prone code.

Why does it work this way?

While I’m not really familiar with how PHP internally handles typehints, my best guess is that the typehint is simply converted into some kind of a string-check. This would explain why the class is never looked up.

If anyone has knowledge about this, please leave a comment.

So hey, another fun little gotcha that feels more like something they just forgot to consider :D

Further reading
For some discussion on wrapping exceptions, read exceptions and abstraction on this blog.