BenMorel
BenMorel

Reputation: 36474

Typehint inherited class variables in PHPStorm

In PHPStorm, I can type-hint a variable this way:

/** @var Point $point */
$point->x();

However, say I inherited a variable from a parent class, and want to type-hint it:

class PointProxy extends Proxy
{
    public function x()
    {
        ...

        /** @var Point $this->geometry */
        return $this->geometry->x();
    }
}

This doesn't work, PHPStorm acts as if I had type-hinted $this, and not $this->geometry.

Is there a way to make such a type-hint work without redeclaring the $geometry property in the subclass, or is this unsupported?

Upvotes: 7

Views: 2647

Answers (3)

puiu
puiu

Reputation: 726

I ran into a very similar problem. I had a generic storage class that dealt with database operations and then a proxy class on top which proxied all storage class methods through a try catch (using __call()) so that I could handle exceptions in one location.

Now whenever I accessed the storage instance like $storage->retrievePhoto($id), the PHPStorm IDE could not typehint for me. My solution involved adding another class name annotation to the $storage object.

For example, see below. Since the specific proxy class is really just a wrapper over the original storage class, it doesn't present any problems although it is still not 100% to my liking but it works.

final class PhotoRepository
{
    /**
     * @var \Repositories\Photos\PhotoStorage
     *      \Repositories\Photos\PhotoStorageExceptionHandlerProxy
     */
    private $storage;

    /**
     * @param \Repositories\Photos\PhotosStorageExceptionHandlerProxy $storage
     */
    public function __construct(PhotosStorageExceptionHandlerProxy $storage)
    {
        $this->storage = $storage;
    }

Upvotes: 0

Steve Reiter
Steve Reiter

Reputation: 1

If the parent object types the property as Geometry but you want it typed as a Point (which descends from Geometry) in your child class, I would recommend creating an accessor in your child class. Possibly with some type checking.

class PointProxy extends Proxy
{
    /**
     * Access the geometry object on parent class as a Point
     *
     * @return Point
     */
    private point()
    {
        if(!is_a($this->geometry, 'Point'))
        {
            // Log an error or something, this is not a state we should be in
        }
        else
        {
            return $this->geometry;
        }
    }

    public function x()
    {
    ...

        return $this->point->x();
    }
}

Upvotes: 0

funivan
funivan

Reputation: 3433

Try this code. Also you can press alt+enter at undefined properties and select Add @property it will help you to create phpdoc faster.

/**
 * @property Point $geometry
 */
class PointProxy extends Proxy {
  public function x() {
    return $this->geometry->
  }
}

add property completion

Upvotes: 11

Related Questions