PHPDoc 和 __callStatic
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,PhpStorm 3.0 将接受
查看相关功能请求 http://youtrack.jetbrains.net/issue/WI-4051
Well, PhpStorm 3.0 will accept
See relevant feature request http://youtrack.jetbrains.net/issue/WI-4051
一般来说,我认为选择使用神奇的东西需要注意必须接受失去自动完成等有效性的权衡。
然而,在我使用 Eclipse PDT(WinXP 上使用 PHP 5.3.2 的 Helios)进行测试时,我能够从我根据您的示例建模的 Loader 类中的一个显式静态方法和两个神奇的静态方法获得良好的自动完成功能。
简而言之,看来在类 docblock 中使用 @method 标记足以让 Eclipse 解决问题。如果 NetBeans 和 PHPStorm 遇到问题,我不确定它是否与“静态”方面有关......可能只是对此类动态代码的解析可能超出了它们构建的自动完成逻辑来处理的范围。
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.