Php 处理对象数组和intellisense
我发现很多时候我会将自定义对象数组传递给函数进行处理。在我的函数中,在访问内部属性/方法之前,我检查以确保它是正确的类 因为我使用的是数组,而且据我所知PHP没有任何类型化的泛型列表,所以我不能使用类型暗示,所以IDE中的intellisense无法工作,代码检查会抛出警告 我遇到一篇老文章,其中提出了在开发过程中加入这行代码以使intellisense正常工作的想法:Php 处理对象数组和intellisense,php,phpstorm,Php,Phpstorm,我发现很多时候我会将自定义对象数组传递给函数进行处理。在我的函数中,在访问内部属性/方法之前,我检查以确保它是正确的类 因为我使用的是数组,而且据我所知PHP没有任何类型化的泛型列表,所以我不能使用类型暗示,所以IDE中的intellisense无法工作,代码检查会抛出警告 我遇到一篇老文章,其中提出了在开发过程中加入这行代码以使intellisense正常工作的想法: if (false) $myObj = new MyObject(); 因此,我最终得到了一个如下所示的函数: functi
if (false) $myObj = new MyObject();
因此,我最终得到了一个如下所示的函数:
function ProcessObjectArray(array $arrayOfObject)
{
foreach ($arrayOfObject as $key => $myObj) {
if (get_class($myObj) == 'MyNamespace\MyObject') {
if (false) $myObj = new MyObject();
// I can now access intellisense for MyObject in here
} else {
trigger_error('is not right object');
}
}
}
这看起来有点奇怪,所以我想知道这是否是我没有以最佳方式处理对象数组的迹象,或者是否有更好的方式让我的intellisense工作。我查看了arrayobject接口,看看是否可以创建一个实现arrayobject的类,该类将保存一个类型化列表。虽然将所有验证放在其构造函数或类似追加的函数中很好,但我无法让它与intellisense一起工作,因为内部容器仍然只是一个标准数组。另外,使用get\u class
似乎并不好,因为如果重命名了类名或命名空间,那么IDE重构功能就不会选择此引用(好吧,PHPStorm至少不会,我正在使用它)
我当然不需要intellisense,但这种奇怪的黑客行为让我怀疑我是否有正确的PHP OOP方法,并认为我可能遗漏了一些东西。这是正确的方法还是我遗漏了什么?如果你这样做,我会避免使用are本机数组。我将创建包含某种类型数组的类。这样,您可以在类的构造函数中验证数组内容,然后可以使用PHP允许的对象的实际类型提示。使用phpstorm添加注释时,它将正确地为您完成代码
/**
* @param MyNamespace\MyObject[] $arrayOfObject
*/
function ProcessObjectArray(array $arrayOfObject)
{
foreach ($arrayOfObject as $key => $myObj) {
if (get_class($myObj) == 'MyNamespace\MyObject') {
if (false) $myObj = new MyObject();
// I can now access intellisense for MyObject in here
} else {
trigger_error('is not right object');
}
}
}
然而,intellisense不会阻止您传入不正确的对象,它只会在编码时帮助您防止传入不正确的对象
也许您希望考虑使用集合而不是使用通用数组。
有很多例子,但是这里有一个简单的例子,你可以在上面展开class Collection
{
/** @var array */
private $items = [];
/**
* @param MyNamespace\MyObject $obj
* @return $this
*/
public function addItem(MyNamespace\MyObject $obj) {
$this->items[] = $obj;
return $this;
}
/**
* @param $index
* @return $this
*/
public function deleteItem($index) {
unset($this->items[$index]);
return $this;
}
/**
* @param $index
* @return MyNamespace\MyObject|null
*/
public function getItem($index) {
return array_key_exists($index, $this->items) ? $this->items[$index] : null;
}
/**
* @return MyNamespace\MyObject[]
*/
public function getItems() {
return $this->items;
}
/**
* @return int
*/
public function count() {
return sizeOf($this->items);
}
}
下面是一个例子,说明了所有这些是如何工作的:
$collection = new \Collection;
$obj = new MyNamespace\MyObject;
$collection->addItem($obj);
foreach($collection->getItems() as $item) {
// this will already know that $item is MyNamespace\MyObject because of the annotation on the getItems() method
$item->doSomething();
}
这样,除了CollectionElement
之外,您不能向集合中添加任何内容。及之后:
foreach($collection as $element){
/** @var CollectionElement $element */
$element->//here you will have autocompletion
}
你不需要检查任何东西,因为你的集合永远不会包含你不期望的东西。“一般来说,PHP对于任何严肃的类型工作来说都是一种糟糕的语言。”我畏缩。“我畏缩”。只是出于好奇,为什么?我认为PHP是广泛使用的最弱/松散类型,这一点没有争议。我只是尝试了一下,但自动完成不起作用。知道我错过了什么吗?我知道了,没有在current()上指定返回类型。谢谢,使用这样的模式我感觉好多了。当我在另一个函数中迭代它的成员时,如何对这个集合进行注释,使自动补全工作?getItems()上的注释应该可以很好地涵盖这种情况。我将此与其他答案结合起来,得到了完美的结果。谢谢你的帮助!嗯,在您的示例中,您使用getitems()初始化一个数组,然后在该数组上迭代,或者使用for循环和getItem()而不是foreach?
foreach($collection as $element){
/** @var CollectionElement $element */
$element->//here you will have autocompletion
}