PHPDoc 和 __callStatic

2022-08-30 20:39:27

tl;博士

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

动机

如果你想要更大的图景,以下是我如何回答这个问题。

问题:在我目前的项目中,我们有大量的类应该真的是单例(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 并不是必需的。


答案 1

好吧,PhpStorm 3.0会接受的

@method static type name() description

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


答案 2

一般来说,我认为选择使用魔术的东西需要注意,必须接受失去自动完成等东西的有效性的权衡。

但是,在我对Eclipse PDT(在WinXP上使用PHP 5.3.2的Helios)进行测试时,我能够从我的加载器类中获得一个显式静态方法和两个神奇的静态方法的良好自动完成,我按照您的示例建模。

简而言之,在类文档块中使用@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()"

推荐