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

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

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

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


当前回答

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经常这样做。我不知道其他编辑器的情况,但它应该能起作用。

其他回答

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经常这样做。我不知道其他编辑器的情况,但它应该能起作用。

<?php foreach($this->models as /** @var Model_Object_WheelModel */ $model): ?>
    <?php
    // Type hinting now works:
    $model->getImage();
    ?>
<?php endforeach; ?>

我知道我来晚了,但我最近一直在研究这个问题。我希望有人能看到这一点,因为公认的答案虽然是正确的,但并不是最好的方法。至少在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)等方法重写调用这个(现在是私有的)健全检查

我发现了一些有用的东西,它可以拯救生命!

private $userList = array();
$userList = User::fetchAll(); // now $userList is an array of User objects
foreach ($userList as $user) {
   $user instanceof User;
   echo $user->getName();
}

指定一个变量是一个对象数组:

$needles = getAllNeedles();
/* @var $needles Needle[] */
$needles[1]->...                        //codehinting works

这在Netbeans 7.2中工作(我正在使用它)

还与:

$needles = getAllNeedles();
/* @var $needles Needle[] */
foreach ($needles as $needle) {
    $needle->...                        //codehinting works
}

因此,在foreach中使用声明是不必要的。