因此,在PHPDoc中,可以在成员变量声明上方指定@var,以提示其类型。然后一个IDE,例如PHPEd,将知道它正在处理的对象类型,并能够为该变量提供代码洞察力。

<?php
  class Test
  {
    /** @var SomeObj */
    private $someObjInstance;
  }
?>

这很好,直到我需要对对象数组做同样的事情,以便在以后迭代这些对象时能够得到适当的提示。

那么,是否有一种方法来声明PHPDoc标签,以指定成员变量是SomeObjs的数组?@var数组是不够的,@var数组(SomeObj)似乎是无效的,例如。


当前回答

在Zend Studio中使用数组[type]。

在Zend Studio中,数组[MyClass]或数组[int]甚至数组[array[MyClass]]都可以很好地工作。

其他回答

在NetBeans 7.0(可能更低)中,你可以声明返回类型为“数组与文本对象”,就像@return Text和代码提示一样:

编辑:用@Bob Fanger的建议更新了示例

/**
 * get all Tests
 *
 * @return Test|Array $tests
 */
public function getAllTexts(){
    return array(new Test(), new Test());
}

使用它:

$tests =  $controller->getAllTests();
//$tests->         //codehinting works!
//$tests[0]->      //codehinting works!

foreach($tests as $text){
    //$test->      //codehinting works!
}

这并不完美,但总比“混合”要好,因为“混合”没有任何价值。

缺点是你可以将数组作为文本对象,这会抛出错误。

PSR-5: PHPDoc提出了一种泛型风格的表示法。

语法

Type[]
Type<Type>
Type<Type[, Type]...>
Type<Type[|Type]...>

集合中的值甚至可以是另一个数组,甚至是另一个集合。

Type<Type<Type>>
Type<Type<Type[, Type]...>>
Type<Type<Type[|Type]...>>

例子

<?php

$x = [new Name()];
/* @var $x Name[] */

$y = new Collection([new Name()]);
/* @var $y Collection<Name> */

$a = new Collection(); 
$a[] = new Model_User(); 
$a->resetChanges(); 
$a[0]->name = "George"; 
$a->echoChanges();
/* @var $a Collection<Model_User> */

注意:如果你期望IDE来做代码辅助,那么IDE是否支持PHPDoc泛型风格的集合符号就是另一个问题了。

从我对这个问题的回答来看。

Use:

/* @var $objs Test[] */
foreach ($objs as $obj) {
    // Typehinting will occur after typing $obj->
}

在输入内联变量时,和

class A {
    /** @var Test[] */
    private $items;
}

类属性。

2009年PHPDoc(以及像Zend Studio和Netbeans这样的ide)没有这个选项时的先前答案:

你最多只能说,

foreach ($Objs as $Obj)
{
    /* @var $Obj Test */
    // You should be able to get hinting after the preceding line if you type $Obj->
}

我在Zend Studio经常这样做。我不知道其他编辑器的情况,但它应该能起作用。

正如DanielaWaranie在她的回答中提到的——当你在$collectionObject中迭代$items时,有一种方法可以指定$item的类型:将@return MyEntitiesClassName添加到current()以及返回值的Iterator和arrayaccess方法的其余部分。

繁荣!不需要在/** @var SomeObj[] $collectionObj */ over foreach中,与收集对象一起工作,不需要使用特定的方法@return SomeObj[]返回收集。

我怀疑不是所有的IDE都支持它,但它在PhpStorm中工作得很好,这让我更高兴。

例子:

class MyCollection implements Countable, Iterator, ArrayAccess {

    /**
     * @return User
     */
    public function current() {
        return $this->items[$this->cursor];
    }

    //... implement rest of the required `interface` methods and your custom
}

有什么有用的我要添加张贴这个答案

在我的情况下,current()和其余的接口方法是在抽象集合类中实现的,我不知道什么样的实体最终将存储在集合中。

这里有一个技巧:不要在抽象类中指定返回类型,而是在特定的集合类的描述中使用PhpDoc指令@method。

例子:

class User {

    function printLogin() {
        echo $this->login;
    }

}

abstract class MyCollection implements Countable, Iterator, ArrayAccess {

    protected $items = [];

    public function current() {
        return $this->items[$this->cursor];
    }

    //... implement rest of the required `interface` methods and your custom
    //... abstract methods which will be shared among child-classes
}

/**
 * @method User current()
 * ...rest of methods (for ArrayAccess) if needed
 */
class UserCollection extends MyCollection {

    function add(User $user) {
        $this->items[] = $user;
    }

    // User collection specific methods...

}

现在,类的使用:

$collection = new UserCollection();
$collection->add(new User(1));
$collection->add(new User(2));
$collection->add(new User(3));

foreach ($collection as $user) {
    // IDE should `recognize` method `printLogin()` here!
    $user->printLogin();
}

再说一次:我怀疑不是所有的IDE都支持它,但是PhpStorm支持。试试你的,在结果中发表评论!

我知道我来晚了,但我最近一直在研究这个问题。我希望有人能看到这一点,因为公认的答案虽然是正确的,但并不是最好的方法。至少在PHPStorm中没有,不过我还没有测试NetBeans。

最好的方法是扩展ArrayIterator类,而不是使用本机数组类型。这允许你在类级别而不是实例级别输入提示,这意味着你只需要PHPDoc一次,而不是贯穿你的代码(这不仅是混乱的,违反了DRY,但也可能是有问题的,当涉及到重构时PHPStorm有一个重构时丢失PHPDoc的习惯)

参见下面的代码:

class MyObj
{
    private $val;
    public function __construct($val) { $this->val = $val; }
    public function getter() { return $this->val; }
}

/**
 * @method MyObj current()
 */
class MyObjCollection extends ArrayIterator
{
    public function __construct(Array $array = [])
    {
        foreach($array as $object)
        {
            if(!is_a($object, MyObj::class))
            {
                throw new Exception('Invalid object passed to ' . __METHOD__ . ', expected type ' . MyObj::class);
            }
        }
        parent::__construct($array);
    }

    public function echoContents()
    {
        foreach($this as $key => $myObj)
        {
            echo $key . ': ' . $myObj->getter() . '<br>';
        }
    }
}

$myObjCollection = new MyObjCollection([
    new MyObj(1),
    new MyObj('foo'),
    new MyObj('blah'),
    new MyObj(23),
    new MyObj(array())
]);

$myObjCollection->echoContents();

这里的关键是PHPDoc @method MyObj current()覆盖从ArrayIterator继承的返回类型(它是混合的)。这个PHPDoc的包含意味着当我们使用foreach($this as $myObj)遍历类属性时,当引用变量$myObj->…

对我来说,这是实现这一点的最利落的方法(至少在PHP引入类型化数组之前是这样,如果它们曾经这样做过的话),因为我们是在可迭代类中声明迭代器类型,而不是在分散在整个代码中的类实例上声明迭代器类型。

我没有在这里展示扩展ArrayIterator的完整解决方案,所以如果你使用这种技术,你可能还想:

根据需要包括其他类级PHPDoc,例如offsetGet($index)和next() 将完整性检查is_a($object, MyObj::class)从构造函数移到私有方法中 从offsetSet($index, $newval)和appappvalue ($value)等方法重写调用这个(现在是私有的)健全检查