因此,在PHPDoc中,可以在成员变量声明上方指定@var,以提示其类型。然后一个IDE,例如PHPEd,将知道它正在处理的对象类型,并能够为该变量提供代码洞察力。
<?php
class Test
{
/** @var SomeObj */
private $someObjInstance;
}
?>
这很好,直到我需要对对象数组做同样的事情,以便在以后迭代这些对象时能够得到适当的提示。
那么,是否有一种方法来声明PHPDoc标签,以指定成员变量是SomeObjs的数组?@var数组是不够的,@var数组(SomeObj)似乎是无效的,例如。
我知道我来晚了,但我最近一直在研究这个问题。我希望有人能看到这一点,因为公认的答案虽然是正确的,但并不是最好的方法。至少在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)等方法重写调用这个(现在是私有的)健全检查
在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泛型风格的集合符号就是另一个问题了。
从我对这个问题的回答来看。