PHPDoc and __callStatic
tl;dr
What is the correct way to annotate (in PHPDoc) fun开发者_运维技巧ctions 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.
Well, PhpStorm 3.0 will accept
@method static type name() description
See relevant feature request http://youtrack.jetbrains.net/issue/WI-4051
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()"
精彩评论