phpphpstormphp-7.1phpstorm-2017.1

PhpStorm not finding methods in objects created by late static binding by parent abstract class


In my PHP application I have a base class for all database objects, which is further extended by specific model classes. It goes on like this (simplified):

abstract class Model extends Collection {

    (...)

    function __construct(string $primary_key, string $value) {
        $data = MysqlDB::instance() -> select(static::TABLE, implode(',', static::COLUMNS), "$primary_key=\"$value\"");
        if (count($data) != 1)
            throw new ModelException('Select condition uncertain');
        parent::__construct($data[0]);
    }

    public static function getById(string $id) : ?Model {
        try {
            return new static('id', $id);
        } catch (ModelException $e) {
            return NULL;
        }
    }

    (...)

}

The point is, I use the getById function on child classes to obtain the needed objects. However, since the return type of getById method is Model, PhpStorm can't figure out what methods the objects has and highlights the ones I use as an error. Consequently, no type-hinting available.

For instance, assuming that final class User extends Model and that class User has method sendNotification, this kind of code:

User::getById($id) -> sendNotification($param1, $param2, ...)

has sendNotification yellowed out as though it did not exist.

I know this isn't that much of an issue, but it's really irritating in terms of that I get distracted by constant redundant warnings and that I can't use type-hinting in such a usage case.


Solution

  • Try with actual PHPDoc for your getById() where you specify dynamic type (e.g. @return static or @return $this).

    That's the most common way of providing such "this class and its' children" typehint.


    Another possible option is kind of the same .. but using PHP 7.1 functionality (so no PHPDoc blocks).

    Try using self as return type instead of Model. I mean here:

    public static function getById(string $id) : ?Model {
    

    use this instead:

    public static function getById(string $id) : ?self {
    

    But for this one you should use PhpStorm 2017.2 EAP build as 2017.1.x has issues with that (see https://stackoverflow.com/a/44806801/783119 as an example).