Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent a false-warning in PhpStorm when the return-type is deduced incorrectly?

Consider the following code:

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
/**
 * Class MyModel
 * @package App\Models
 * @mixin Builder
 */
class MyModel extends Model
{
    public static function getGreens(): Builder
    {
        return (new self())->where('color', '=', 'green');
    }
}

On the return statement, the PhpStorm (2020.3) complains that:

Return value is expected to be '\Illuminate\Database\Eloquent\Builder', 'MyModel' returned

And suggest to:

Change return type from '\Illuminate\Database\Eloquent\Builder' to 'MyModel'

which is weirdly incorrect (the where method does return an instance of \Illuminate\Database\Eloquent\Builder, while the IDE deduces the return type as being of MyModel type). By removing the return type, the IDE issues another warning:

Missing function's return type declaration

The code works without any problems, but the IDE shouldn't report any false warnings! How should I avoid these warnings in PhpStorm?

PhpStorm (2020.3) complains that: "Return value is expected to be '\Illuminate\Database\Eloquent\Builder', 'MyModel' returned"

like image 907
goodUser Avatar asked Mar 01 '23 19:03

goodUser


1 Answers

It's a result of not following the "best practices". The class-hierarchy of MyModel does not provide a method of where; in other words, such a method does not exist in the class-hierarchy. But! The parent class of Model does provide a magic method of __call() which gets triggered when an inaccessible method in the object context is invoked (in your case, the method of where). It essentially forwards the "call" to a new instance of \Illuminate\Database\Eloquent\Builder, that has the implementation of the requested method (it's acquired from invoking the method of newQuery()). This mechanism is not only IDE-unfriendly, but also slower.

Thus; drop the @mixin tag, and instead of utilizing the "magic methods", use "native access":

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class MyModel extends Model
{
    public static function getGreens(): Builder
    {
        return (new self())->newQuery()->where('color', '=', 'green');
        //                 ^^^^^^^^^^^^
    }
}
like image 78
someOne Avatar answered Mar 05 '23 14:03

someOne