Compizfox Compizfox - 11 months ago 63
PHP Question

Returning NULL with return type declarations

I was refactoring a codebase for use with PHP7, particularly implementing scalar type hints and return type hints, when I encountered an problem.

I have a class with some properties, one of which an id. This id is not mandatory (you can construct an object without setting the id). When creating a new object of this class you don't set the id, and it gets an id as soon as it is inserted into the db (by a separate mapper class).

This mapper class needs to check if the object already exists in the db, and it does this by checking if the id is set:

if(empty($exampleObject->getId())) {
// Insert object
} else {
// Update object

I was applying return type hints to every function in my codebase, and the problem is that the function
can't return NULL if I enforce an int return type. It TypeErrors, even without having strict typing enabled:

Fatal error: Uncaught TypeError: Return value of ExampleClass::getId() must be of the type integer, null returned

I considered not setting a return type hint for this getter, but I then realised the problem is probably not the return type hinting, but the fact that I'm using mixed return types. I remember reading somewhere that using mixed return types is a bad thing, but I'm not sure how to tackle this without using mixed return types. I could:

  • Throw an exception in the getter, and design the check in the mapper class so that it catches that exception.

  • Catch the TypeError exception, and use that to indicate the id is not set.

  • Make the id property public, so I can call isset directly on that.

  • Add a different method
    hasId() return isset($this->id)

Frankly, don't really like any of these solutions, and I was wondering if there's a better option. What's the best practise for cases like this?

Also, shouldn't I only get a TypeError if I have strict typing enabled? I thought PHP7 defaulted to "weak type hints".

Answer Source

The best answer, for now (PHP 7.0), is to simply omit the type declaration and use a docblock. We don't currently have a way to specify that a function returns a type or null.

When PHP 7.1 is released, you will be able to use nullable types, where you put a question mark before the type name to mark the return type as accepting both that type and null:

public function getId(): ?int {
    /* … */

However, at the time of writing (2016-09-04), PHP 7.1 had not yet been released.