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 getId()
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:
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".
PHP 7.1 added 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 {
/* … */
}
If you're still on PHP 7.0, I suggest omitting the type declaration and using a docblock.