PHPDoc和__callStatic

时间:2011-05-12 18:01:13

标签: php phpdoc magic-methods

TL;博士

通过__callStatic实现注释(在PHPDoc中)函数的正确方法是什么?更重要的是:有没有办法让NetBeans PHPStorm理解这些是静态方法?

动机

如果你想要更大的图片,这就是我对这个问题的看法。

问题:在我目前的项目中,我们有很多类应该是单例(DB代理等)。不用说,我们至少有几百require_once$foo = new FooProxy();行。

解决方案:我使用Loader魔术方法创建了__callStatic类来解决此问题,因此我们可以说$foo = Loader::FooProxy();。它非常适合我们的目的,但是:

问题:这样在团队中使用的IDE中显然没有类型提示。

解决方案:每个模块都定义了Loader的子类,添加了仅路由到__callStatic的方法。

问题:为了自动完成而添加实际解释的代码是不可接受的(这可以争论,但我们暂时接受它。)

解决方案:我们不添加任何真正的方法,只在PHPDoc中声明方法如下:

<?php
/**
 * @method FooProxy FooProxy()
 */
 class BarLoader extends Loader {}
?>

问题FooProxy不是静态方法。以下所有内容都不会使其静止:

<?php
/**
 * @static
 * @method FooProxy FooProxy()
 */

///////////////

/**
 * @static @method A A()
 * @method static A A()
 * @method A static A()
 * @method A A() static
 */

使类抽象没有区别。大约一个小时的谷歌没有出现任何解决方案。主要目标是让IDE了解这些功能;拥有正确的PHPDoc并不是必需的。

2 个答案:

答案 0 :(得分:30)

好吧,PhpStorm 3.0将接受

@method static type name() description

查看相关功能请求http://youtrack.jetbrains.net/issue/WI-4051

答案 1 :(得分:1)

一般来说,我认为使用神奇的东西的选择需要注意不得不接受失去自动完成等功能的权衡。

然而,在我使用Eclipse PDT(在WinXP上使用PHP 5.3.2的Helios)进行测试时,我能够通过一个显式静态方法和我的Loader类中的两个魔术静态方法获得良好的自动完成功能。

简而言之,似乎在docblock类中使用@method标记足以让Eclipse解决问题。如果NetBeans和PHPStorm遇到问题,我不确定它是否与“静态”方面有关......它可能只是解析这样的动态代码可能比自动完成逻辑的构建要处理的更多。

<?php
/**
 * @method BarProxy BarProxy() returns an instance of BarProxy
 * @method BazProxy BazProxy() returns an instance of BazProxy
 */
class Loader
{
    public static function __callStatic($name, $arguments)
    {
        return new $name($arguments);
    }

    /**
     * @return FooProxy
     */
    public static function FooProxy(){
        return new FooProxy();
    }
}

class FooProxy
{
    public function sayCheese() {}
}

class BarProxy
{
    public function eatFries() {}
}

class BazProxy
{
    public function sleep() {}
}

$foo = Loader::FooProxy();
$foo->sayCheese(); // did this simply to verify explicit autocompletion succeeded

$bar = Loader::BarProxy();
$bar->eatFries();  // autocompletion of just "$bar->" brought up "eatFries()"

$baz = Loader::BazProxy();
$baz->sleep();     // autocompletion of just "$baz->" brought up "sleep()"