Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper phpdoc comment for iteratable object?

I'm having a bit of a problem trying to get a correct autocompletion for the following code example. I'm using PHPStorm 7 on a Win7 machine.

First just a simple class.

/**
 * Class myObject
 */
class myObject
{
    /**
     * some method
     */
    public function myMethod()
    {
        // do something
    }
}

This one is the collection class which can contain multiple instances of the prior class and implements the IteratorAggregate interface.

/**
 * Class myCollection
 */
class myCollection implements IteratorAggregate
{
    /**
     * @var myObject[]
     */
    protected $_objects = array();


    /**
     * @param myObject $object
     * @return myCollection
     */
    public function add(myObject $object)
    {
        $this->_objects[] = $object;

        return $this;
    }


    /**
     * @return ArrayIterator
     */
    public function getIterator()
    {
        return new ArrayIterator($this->_objects);
    }
}

And here is the code example.

$collection = new myCollection;

$collection->add(new myObject);
$collection->add(new myObject);

foreach ($collection as $object) {
    $object->myMethod(); // gets no autocompletion
}

As you may have guessed (and read in the example) the myMethod() call gets not autocompleted and is beeing listed in the code analysis. The only way i found is adding a comment block for $object, which i find, to be honest, extremely annoying.

/** @var $object myObject */
foreach ($collection as $object) {
    $object->myMethod(); // gets autocompletion now, but sucks
}

So, any ideas or fundamented knowledge on how to solve this?

like image 753
user1506674 Avatar asked Mar 08 '14 17:03

user1506674


3 Answers

/**
 * @return ArrayIterator|myObject[]
 */
public function getIterator()
{
    return new ArrayIterator($this->_objects);
}

For extended classes (the base class is above):

/**
 * @method myObject[] getIterator()
 */
class ExtendedClass extends BaseCollection
{
}

or

/**
 * @method iterable<myObject> getIterator()
 */
class ExtendedClass extends BaseCollection
{
}

I think this will be best way to handle such case. at least it works with PHPStorm

like image 108
Neznajka Avatar answered Nov 17 '22 01:11

Neznajka


Your

/** @var $object myObject */

block is indeed the correct way to accomplish this. The syntax you are expecting to do the work,

/** * @var myObject[] */

is not standard phpdoc notation, although it is in informal use and has some effort ongoing to standardize. Until such standardization does happen, IDEs recognizing it will probably be hit-or-miss. IDE coverage of your $object local var block is also hit-or-miss, actually.

like image 38
ashnazg Avatar answered Nov 17 '22 02:11

ashnazg


In your myCollection class, override current() as follows:

/** @return myObject */
public function current() {
    return parent::current();
}
like image 1
user2634914 Avatar answered Nov 17 '22 01:11

user2634914