Unexpected Type Issue in a PHP Model

While using Psalm, Vimeo’s static type analysis tool for PHP, I ran into an unexpected type issue on a couple of model files.

This is a snippet of code similar to the one that generated the error:

/** 
* @param int $id
* @return array
*/
public function one(int $id):array 
{
    // ...
}

This worked perfectly fine until I started type testing with Psalm, when the above code started generating an error:

ERROR: MismatchingDocblockParamType - app/Models/BookModel.php:13:15 - 
Parameter $id has wrong type 'int', should be 'string'

The error was a result of this call during a Unit Test:

$id = $model->save(); // returns last insert id
$model->one($id);

My reaction to the error was, as you might expect, WTF? But further investigation revealed why. $id definitely held a numeric value, but it was a string representation of that value; PDO::lastInsertId(), it turns out, returns strings, not integers, even for auto incrementing primary keys. I assume this is in case the insert id can’t be represented in 32bits. Anyway, PHP’s documentation confirmed that lastInsertId() returns a string. In some cases, in my models, I had been doing conversions like intval($id) just to be safe, but I was wrong.

I would likely never have noticed this before using Psalm. Anyway, long story short, I corrected the issue in both model and calling scripts, and Psalm was happy.