PHPDoc 和 __callStatic

发布于 2024-11-07 04:59:53 字数 1225 浏览 0 评论 0原文

tl;dr

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

动机

如果你想要更全面的了解,以下是我提出这个问题的方法。

问题:在我当前的项目中,我们有大量的类实际上应该是单例(数据库代理等)。不用说,我们至少有几百行 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 并不是真正必要的。

tl;dr

What is the correct way to annotate (in PHPDoc) functions implemented via __callStatic? More important: is there a way that will make NetBeans and PHPStorm understand that these are static methods?

Motivation

If you want the bigger picture, here's how I got to this question.

Problem: In my current project we have a ton of classes that should really be singletons (DB proxies and the like). Needless to say, we have at least a few hundred require_once and $foo = new FooProxy(); lines.

Solution: I created a Loader class to solve this, using the __callStatic magic method so we can just say $foo = Loader::FooProxy();. It's perfect for our purposes, but:

Problem: This way there's obviously no type hinting in either IDE used in the team.

Solution: Every module defines a subclass of Loader, adding methods that just route to __callStatic.

Problem: Adding actually interpreted code just for auto-completion's sake is not acceptable (this could be argued, but let's accept it for the time being).

Solution: Let's not add any real methods, only declare the methods in PHPDoc like this:

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

Problem: FooProxy is not a static method. None of the following make it static either:

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

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

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

Making the class abstract makes no difference. About an hour of Google'ing turned up no solutions. The primary goal is to make the IDEs aware of these functions; having correct PHPDoc is not really a necessity.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

愛上了 2024-11-14 04:59:54

好吧,PhpStorm 3.0 将接受

@method static type name() description

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

Well, PhpStorm 3.0 will accept

@method static type name() description

See relevant feature request http://youtrack.jetbrains.net/issue/WI-4051

迷你仙 2024-11-14 04:59:54

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

然而,在我使用 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()"

Generally speaking, I think the choice of using the magic stuff comes with caveat of having to accept a tradeoff of losing the effectiveness of things like autocompletion.

However, in my testing with Eclipse PDT (Helios with PHP 5.3.2 on WinXP), I was able to get good autocompletions from one explicit static method and two magic static methods out of my Loader class that I modeled after your example.

In short, it appears the use of the @method tag in the class docblock was enough for Eclipse to figure things out. If NetBeans and PHPStorm are having trouble, I'm not sure if it's related to the "static" aspect or not... it may just be that the parsing of such dynamic code may be more than their autocompletion logic is built to handle.

<?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()"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文