0

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.

2
  • 2
    1) Try with actual PHPDoc for your getById() where you specify dynamic type (e.g.@return static or @return $this) 2) Kind of the same .. but using PHP 7.1 functionality -- try using self as return type instead of Model (I mean here: ...getById(string $id) : ?Model). But for this one you should use 2017.2 EAP build as 2017.1 has issues with that (see stackoverflow.com/a/44806801/783119) Commented Jul 4, 2017 at 18:26
  • Thanks, @return static worked perfectly Commented Jul 4, 2017 at 18:36

2 Answers 2

2

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).

Sign up to request clarification or add additional context in comments.

Comments

1

There are three ways to achieve this, none of them has anything to do with PHPStorm.

First overwrite the method in every child with the proper return type:

/**
 * @return User
 */
public static function getById(string $id) : ?Model { return parent::getById($id); }

Second add all possible children to the return tag of the abstract class.

/**
 * @return Model|User|...
 */
public static function getById(string $id) : ?Model { /* ... */ }

Third add a type hint just in place:

/** @var User $user */
$user = User::getById($id);
$user->sendNotification($param1, $param2, ...);

These are not nice and hard to maintain. But there is no "setting" in PHPStorm for that.

3 Comments

I would not consider #1 and #2 as possible options. I mean -- yes, it will do ... but it's ugly and extra job for no reason.
That's what I said. I am not recommending any of them, but they are workarounds for the proposed problem.
Sure. I just have some other ideas in mind -- see my comment below the actual question -- that may work (don't have 7.1 and such code to test .. but in theory it should work).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.