Як документувати магічні (_call та _callStatic) методи для IDE


81

Після багатьох щасливих років кодування в notepad ++ та sublime, мені порадили спробувати PHP IDE. Я випробовую phpStorm, і це здається приємним. Заповнення коду та документація - чудова функція, але вона не працює у мене, коли використовуються магічні методи. Чи існує якась робота, щоб отримати phpStorm, щоб зрозуміти, що відбувається в магічних методах?

Наша ситуація приблизно така:

abstract class a {
    public static function __callStatic($method,$args)
    {
        if(strpos($method,"get_by_") === 0)
        {
            //do stuff
        } elseif(strpos($method,"get_first_by_") === 0) {
            //do stuff
        } elseif($method == "get_all") {
            //do stuff
        }
    }
}

class b extends a {
    // some more stuff
}

b::get_by_user_id(27);
b::get_first_by_id(156);
b::get_all();

The magic callStatic method allows us to get a collection of objects via 1 or more arguments that make up the function call.

I see that there is an @method statement for use in these cases but phpStorm is only picking up the first of these statements. Furthermore I can only set the return type to mixed where as I'd prefer to be able to set it as whatever class this was called on (b in my example).

Any ideas or suggestions would be very gratefully received, thanks.


1
WHY WOULD ANYONE THINK THAT OVERRIDING _call IS A GOOD IDEA?!!
Brian Gordon

Gotta say, +1'd Brian's comment in the event that any sane person is going to find this question. Magic methods are for all intents and purposes: undocumentable (try to document a(n) [parameter|precondition|postcondtion|exception] to a magic method), not IDE-friendly (try to step debug a magic method), resilient to refactoring (please, don't even consider trying to refactor a magic method in a tenured piece of software), and LAZY (ok, the last one might be construed as an opinion).
Luke A. Leber

17
-1 to the opinion in the comment by @LukeA.Leber as it evidences a lack of vision. While magic methods are not a way to write less code (if you are using them to be lazy), magic methods make architectures possible that simple would not otherwise possible or that would be so outrageously complex it would not be worth writing. And they are completely IDE friendly when using PHPDoc. Note that most of the time you do not need magic methods, but when you need them there is no substitute (in PHP.) When they are used in a very structured manner using them is a completed valid solution.
MikeSchinkel

5
Don't think overriding __call is a bad idea. It's all about implementation. The implementation shown in the question above definitely wouldn't be the best way, but for chain-able API's, it allows a lot of flexibility.
Steve Bauman

Відповіді:


144

Use class-level PHPDoc comment -- specifically @method tag -- works fine in PhpStorm:

/**
 * @method static someClass get_by_user_id(int $id) Bla-bla
 * @method static someClass get_first_by_id(int $id) 
 */
abstract class a {
...

In the above:

  • @method -- PHPDoc tag
  • static -- tells that this is static method
  • someClass or $this -- return type
  • get_by_user_id -- method name
  • (int $id) -- method signature: ([[type] [parameter]<, ...>])
  • Bla-bla -- some optional description

More about @method:

P.S. While @method static works fine in PhpStorm (tells IDE that method is static) it may not be (yet?) supported by actual phpDocumentor tool (sorry, have not used it for a while).


Alternatively: (in PhpStorm, of course) Settings | Inspections | PHP | Undefined | Undefined method --> Downgrade severity if __magic methods are present in class -- it will not help with code completion for such methods in any way, but will not mark those magic methods as "undefined method" errors.


phpDocumentor's ticket regarding using RegEx/partial names for @property/@method tags (how it can be useful for documentation and how little help it may bring to the actual IDE when dealing with code completion):


2
Thanks, this looks like a reasonable suggestion and it certainly works in phpStorm, but I'm a bit loathed to write out the potentially hundreds of lines of @method at the top of each class. You see the get_by_* method can be prepended by any of the objects parameters to get objects of that type by the specified parameter. Even excluding the possibility of get_by__and_ i'd end up with about 1500 @methods across 140 different class. Is there not a more generic way to provide documentation?
Rob Forrest

No. All magic methods must be declared specifically (that's the main point of documenting this way) - PHPDoc does not understand partial names (e.g. get_by_*(int $id)). For IDE (code inspection, not completion!) you have alt solution (disable warnings). For phpDocumentor (or alternative tool) - no solution known to me (maybe it is there, but I do not know about it). You have the link to github - file new ticket and ask for adding such "partial names" matching functionality - see what they will say (most likely will be rejected). If it will be implemented, then IDE may have it as well later.
LazyOne

github.com/phpDocumentor/phpDocumentor2/issues -- but please check if similar ticket does not exist before posting yours.
LazyOne

Thanks for all of that. There is a currently open ticket with regards to this but it all seems to have gone quiet. I've stuck a comment in there and we'll see what comes of it.
Rob Forrest

2
Just for the reference, the phpDocumentor's ticket (so other users know what ticket you are talking about; also added it to the answer itself): github.com/phpDocumentor/phpDocumentor2/issues/689
LazyOne

4

Somewhat related to original question:

You can also define this in phpstorm meta file. Here's an example for factory method (v2016.3):

// Define in .phpstorm.meta.php
namespace PHPSTORM_META {
    $STATIC_METHOD_TYPES = [
        \Factory::create('') => [],
    ];
}

// Then use in code
$factory = new \Factory();
$user = $factory->create(\User::class);
// Here you get autocomplete.
$user->subscribe();

This way you don't have to docblock every possibility when magic happens.

Have some docs for details.


This doesn't work with __call. It's also not documented and invalid PHP. PHPStorm only provides support for where you have statically defined methods that return a mixture of types depending on the input.
jgmjgm
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.