PHPDoc类型提示对象数组?

Art*_*kii 399 php ide var phpdoc hint

因此,在PHPDoc中,可以@var在成员变量声明之上指定提示其类型.然后是一个IDE,例如.PHPEd将知道它正在使用什么类型的对象,并且能够为该变量提供代码洞察.

<?php
  class Test
  {
    /** @var SomeObj */
    private $someObjInstance;
  }
?>
Run Code Online (Sandbox Code Playgroud)

这很有效,直到我需要对一个对象数组做同样的事情,以便在稍后迭代这些对象时能够获得正确的提示.

那么,有没有办法声明一个PHPDoc标记来指定成员变量是一个SomeObjs 数组?@var例如,数组是不够的,@var array(SomeObj)似乎没有效果.

Nis*_*shi 888

在JetBrains的PhpStorm IDE中,您可以使用/** @var SomeObj[] */,例如:

/**
 * @return SomeObj[]
 */
function getSomeObjects() {...}
Run Code Online (Sandbox Code Playgroud)

PHPDoc的文档建议使用此方法:

如果指定包含单个类型,则Type定义会通知读者每个数组元素的类型.然后只需要一个Type作为给定数组的元素.

例: @return int[]

  • 我刚下载并且过去一周一直在使用phpstorm.击败Aptana(这是免费的伟大).这正是我所寻找的.实际上,就像你为JavaScript做的那样,我应该猜到了 (10认同)
  • @fishbone @Keyo现在可以在Netbeans中运行(至少在7.1晚上构建,也许更早),虽然看起来你需要使用一个临时变量(一个bug?).提示`foreach(getSomeObjects()as $ obj)`不起作用,但它对`$ objs = getSomeObjects(); foreach($ objs as $ obj)` (10认同)
  • 这在Netbeans中不起作用,我很失望.Jetbrains制作了一些非常好的工具. (5认同)
  • 谢啦!这正是我所寻找的.PHPStorm太棒了. (3认同)
  • 将@var Obj [string]用于关联数组会很高兴. (2认同)

Zah*_*aka 314

使用:

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

当键入内联变量时,和

class A {
    /** @var Test[] */
    private $items;
}
Run Code Online (Sandbox Code Playgroud)

对于类属性.

从09年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->
}
Run Code Online (Sandbox Code Playgroud)

我在Zend Studio中做了很多.不了解其他编辑,但它应该工作.

  • **请确保你看下面!**我几乎没有向下滚动 - 本来是一个很大的错误!**许多IDE都支持更好的语法!**(提示:`@var Object [] $ objects`表示"$ objects"是Object的一个实例数组.) (179认同)
  • 这也适用于Jetbrains PHPStorm 2.x. (21认同)
  • 在Netbeans 7中注意,似乎重要的是你只有一个星号 - "/**@var $ Obj Test*/`不起作用. (14认同)
  • `/**@var TYPE $ variable_name*/`是正确的语法; 不要颠倒类型和变量名称的顺序(如评论中前面所建议的那样),因为它在所有情况下都不起作用. (8认同)
  • 这是有道理的,但它不适用于PHPEd 5.2.我唯一能想到的就是foreach($ Objs as/**@var Test*/$ Obj),这非常难看.:( (3认同)
  • @contrebis:"@ var"是有效的docblock标记.因此,即使您的IDE在docblock"/**...*/"中不支持它,并且仅支持"/*...*/"中的"@var" - 请不要更改正确的docblock.向IDE的错误跟踪器提出问题,以使IDE符合标准.想象一下,您的开发团队/外部开发人员/社区使用不同的IDE.保持原样并为将来做好准备. (3认同)
  • 这适用于NetBeans 6.7(我认为它有问题,因为当你点击ctrl-space时你会得到一个?类型,但它**可以自动完成对象的成员/方法). (2认同)
  • 在NetBeans 6.8+中使用.$ Obj->然后ctrl-space显示属性和方法的期望列表. (2认同)

use*_*819 56

Netbeans提示:

你得到的代码完成的$users[0]->$this->用户类的数组.

/**
 * @var User[]
 */
var $users = array();
Run Code Online (Sandbox Code Playgroud)

完成后,您还可以在类成员列表中看到数组的类型 $this->...

  • 也适用于PhpStorm 9 EAP:/***@var UserInterface []*/var $ users = []; //实现接口的Objs数组 (4认同)

Hig*_*don 29

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

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

这适用于Netbeans 7.2(我正在使用它)

也适用于:

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

因此,在内部使用声明foreach是没有必要的.

  • 这个解决方案比我认为的接受答案更清晰,因为你可以多次使用foreach,类型提示将继续使用每次新的`/*@var $ Obj Test*/`注释. (2认同)

Ger*_*che 21

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

句法

Type[]
Type<Type>
Type<Type[, Type]...>
Type<Type[|Type]...>
Run Code Online (Sandbox Code Playgroud)

Collection中的值甚至可以是另一个数组,甚至是另一个Collection.

Type<Type<Type>>
Type<Type<Type[, Type]...>>
Type<Type<Type[|Type]...>>
Run Code Online (Sandbox Code Playgroud)

例子

<?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> */
Run Code Online (Sandbox Code Playgroud)

注意:如果您希望IDE执行代码辅助,那么关于IDE是否支持PHPDoc通用样式集合表示法的另一个问题.

从我对这个问题的回答.

  • 通用符号[**已从 PSR-5 中移除**](https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc.md) (5认同)

Dan*_*nie 12

我更喜欢阅读和编写干净的代码 - 正如Robert C. Martin在"清洁代码"中所述.遵循他的信条,您不应要求开发人员(作为您的API的用户)知道您的阵列的(内部)结构.

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

如您所述,您希望将该数组(包含对象)用作一维数组.

如Nishi所述,您可以使用:

/**
 * @return SomeObj[]
 */
Run Code Online (Sandbox Code Playgroud)

为了那个原因.

但同样:请注意 - 这不是标准的docblock表示法.这种表示法是由一些IDE生产者引入的.

好的,好吧,作为开发人员,你知道"[]"与PHP中的数组相关联.但在普通的PHP上下文中,"某些东西[]"是什么意思呢?"[]"表示:在"某事物"中创建新元素.新元素可能就是一切.但是你要表达的是:具有相同类型和确切类型的对象数组.如您所见,IDE生产者引入了新的上下文.您必须学习的新环境.其他PHP开发人员必须学习的新上下文(了解您的docblock).糟糕的风格(!).

因为您的数组确实有一个维度,您可能希望将"对象数组"称为"列表".请注意,"list"在其他编程语言中具有非常特殊的含义.例如,将它称为"集合"会更好.

请记住:您使用的编程语言可以为您提供OOP的所有选项.使用类而不是数组,使类可以像数组一样遍历.例如:

class orderCollection implements ArrayIterator
Run Code Online (Sandbox Code Playgroud)

或者,如果要将内部对象存储在多维数组/对象结构中的不同级别上:

class orderCollection implements RecursiveArrayIterator
Run Code Online (Sandbox Code Playgroud)

此解决方案用"orderCollection"类型的对象替换您的数组,但到目前为止还没有在IDE中启用代码完成.好的.下一步:

实现由docblocks接口引入的方法 - 特别是:

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

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

/**
 * [...]
 * @return Order
 */
orderCollection::offsetGet()
Run Code Online (Sandbox Code Playgroud)

不要忘记使用类型提示:

orderCollection::append(Order $order)
orderCollection::offsetSet(Order $order)
Run Code Online (Sandbox Code Playgroud)

这个解决方案停止引入了很多:

/** @var $key ... */
/** @var $value ... */
Run Code Online (Sandbox Code Playgroud)

在你的代码文件中(例如在循环内),正如Zahymaka用她/他的回答证实的那样.您的API用户不必强制引入该docblock,以完成代码.仅在一个位置上使用@return会将冗余(@var)减少为尽可能多的变量.使用@var"撒上"docBlocks"会使您的代码更具可读性.

最后你完成了.看起来难以实现?看起来像拿大锤来破解坚果?不是真的,因为你熟悉那些接口和干净的代码.请记住:您的源代码是一次写入/多次读取.

如果IDE的代码完成无法使用此方法,请切换到更好的方法(例如IntelliJ IDEA,PhpStorm,Netbeans)或在IDE生产者的问题跟踪器上提交功能请求.

感谢Christian Weiss(来自德国)作为我的教练和教我如此出色的东西.PS:在XING上和我见面.

  • 也许在2012年,这不是"标准",但[现在](http://phpdoc.org/docs/latest/guides/types.html#arrays)它被描述为phpDoc的内置功能. (2认同)

Max*_*Max 11

如果您使用 PHPStorm 2021.2+ 和 VS Code 以及 PHP Intelephense 扩展,您还可以使用以下语法(数组形状):

@property array{name: string, content: string}[] $files
Run Code Online (Sandbox Code Playgroud)

或者

@var array{name: string, content: string}[] $files
Run Code Online (Sandbox Code Playgroud)


d.r*_*aev 5

在NetBeans 7.0(也可能更低)中,您可以声明返回类型"带有Text对象的数组" @return Text,代码提示将起作用:

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

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

并使用它:

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

foreach($tests as $text){
    //$test->      //codehinting works!
}
Run Code Online (Sandbox Code Playgroud)

它并不完美,但它只是让它"混合"更好,这没有任何价值.

CONS是允许您将数组作为文本对象进行操作,这将导致错误.

  • 这是一个**解决方法**,而不是解决方案。你在这里所说的是“这个函数可能返回一个'Test'类型的对象,或者一个数组”。然而,从技术上讲,它并没有告诉您有关数组中可能包含的内容的任何信息。 (2认同)

Eri*_*son 5

array[type]在Zend Studio中使用。

在Zend Studio的,array[MyClass]或者array[int]甚至是array[array[MyClass]]工作的高度。


Pav*_*vel 5

作为DanielaWaranie在她的答复中提到-有指定$项目类型的方式,当你遍历在$ $ collectionObject项目:添加@return MyEntitiesClassNamecurrent()了的休息IteratorArrayAccess其返回值-方法.

繁荣!无需在/** @var SomeObj[] $collectionObj */结束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
}
Run Code Online (Sandbox Code Playgroud)

我将添加发布此答案的有用之处

在我的情况下current(),其余的interface-methods在Abstract-collection类中实现,我不知道哪种实体最终将存储在集合中.

所以这里的诀窍是:不要在抽象类中指定返回类型,而是@method在特定集合类的描述中使用PhpDoc instuction .

例:

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...

}
Run Code Online (Sandbox Code Playgroud)

现在,使用类:

$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();
}
Run Code Online (Sandbox Code Playgroud)

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