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

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

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

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


当前回答

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泛型风格的集合符号就是另一个问题了。

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

其他回答

我更喜欢阅读和编写干净的代码——正如Robert C. Martin在“干净的代码”中概述的那样。 在遵循他的信条时,你不应该要求开发人员(作为API的用户)知道数组的(内部)结构。

API用户可能会问:这是一个只有一维的数组吗?对象是否分布在多维数组的所有层次上?有多少嵌套循环(foreach等)我需要访问所有对象?什么类型的对象被“存储”在该数组中?

正如您所概述的,您希望将该数组(其中包含对象)用作一维数组。

正如Nishi所述,你可以使用:

/**
 * @return SomeObj[]
 */

的。

但是,请再次注意—这不是标准的文档块表示法。这个符号是由一些IDE生产者引入的。

好吧,好吧,作为开发人员,您知道“[]”与PHP中的数组绑定。但是“something[]”在正常的PHP上下文中是什么意思呢?“[]”表示:在“某物”中创建新元素。新元素可以是一切。但你想表达的是:具有相同类型和确切类型的对象数组。如您所见,IDE生成器引入了一个新的上下文。一个你必须学习的新环境。其他PHP开发人员必须学习的新上下文(以理解您的文档块)。糟糕的风格!

因为你的数组只有一个维度,你可能想把这个“对象数组”称为“列表”。请注意,“list”在其他编程语言中具有非常特殊的含义。例如,将其称为“集合”会更好。

请记住:您使用的编程语言支持所有面向对象的选项。 使用类而不是数组,并使您的类像数组一样可遍历。例如:

class orderCollection implements ArrayIterator

或者如果你想在多维数组/对象结构的不同层次上存储内部对象:

class orderCollection implements RecursiveArrayIterator

该解决方案将数组替换为“orderCollection”类型的对象,但到目前为止还没有在IDE中启用代码完成功能。好的。下一步:

实现由docblock接口引入的方法——特别是:

/**
 * [...]
 * @return Order
 */
orderCollection::current()

/**
 * [...]
 * @return integer E.g. database identifier of the order
 */
orderCollection::key()

/**
 * [...]
 * @return Order
 */
orderCollection::offsetGet()

不要忘记在以下情况下使用类型提示:

orderCollection::append(Order $order)
orderCollection::offsetSet(Order $order)

这个解决方案不再引入很多:

/** @var $key ... */
/** @var $value ... */

在你的代码文件中(例如在循环中),正如Zahymaka与她/他的回答所确认的那样。你的API用户不需要强制引入文档块来完成代码。只在一个地方使用@return可以尽可能地减少冗余(@var)。在“docBlocks”中添加@var会让你的代码可读性最差。

最后你完成了。看起来很难实现?看起来像拿大锤砸坚果?不完全是,因为您熟悉这些接口和干净的代码。记住:你的源代码只写一次/读很多次。

如果您的IDE的代码完成不适合这种方法,请切换到更好的方法(例如IntelliJ IDEA, PhpStorm, Netbeans)或在IDE生成器的问题跟踪器上提交特性请求。

感谢克里斯蒂安·韦斯(来自德国)作为我的教练,教我这么棒的东西。PS:在XING上见我和他。

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

问题是@var只能表示一个类型-不包含复杂的公式。如果你有一个语法的“数组的Foo”,为什么停在那里,不添加一个语法的数组的数组,其中包含2个Foo和3个Bar”?我知道元素列表可能比这更通用,但这是一个滑坡。

就我个人而言,我有时会使用@var Foo[]来表示“Foo的数组”,但IDE不支持。

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