如何为IDE记录魔术(_call和_callStatic)方法


80

在用记事本++和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();

神奇的callStatic方法使我们能够通过1个或多个组成函数调用的参数来获取对象的集合。

我看到在这些情况下有一个@method语句可以使用,但是phpStorm仅选择了这些语句中的第一个。此外,我只能将返回类型设置为“ mixed”,因为我希望能够将其设置为被调用的任何类(在我的示例中为b)。

任何想法或建议都会非常感激,谢谢。


1
为什么会任何人认为压倒性_call是一个好主意?!
Brian Gordon

得说,如果任何理智的人都会找到这个问题,则+1布莱恩的评论。魔术方法具有所有意图和目的:不可记录(尝试将a(n)[参数|条件|后置条件|异常]记录为魔术方法),不兼容IDE(尝试逐步调试魔术方法),可重构(请不要考虑尝试在使用期限较长的软件中重构一种魔术方法)和LAZY(好的,最后一个可以解释为一种意见)。
路加·莱伯

16
@ LukeA.Leber评论中的-1,因为它表明缺乏远见。尽管魔术方法不是编写更少代码的方法(如果您懒惰地使用它们),魔术方法使体系结构成为可能,否则将无法实现简单的设计,或者使结构过于复杂以至于不值得编写。使用PHPDoc时,它们是完全IDE友好的。请注意,大多数时候您不需要魔术方法,但是当您需要魔术方法时,就没有替代方法(在PHP中。)以非常结构化的方式使用它们时,它们是完整的有效解决方案。
MikeSchinkel '17

5
不要认为重写__call是一个坏主意。一切都与实施有关。上面问题中显示的实现绝对不是最好的方法,但是对于可链接的API,它具有很大的灵活性。
史蒂夫·鲍曼

Answers:


143

使用类级别的PHPDoc注释-特别是@method标记-在PhpStorm中可以正常工作:

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

在上面:

  • @method -PHPDoc标签
  • static -告诉这是静态方法
  • someClass$this-返回类型
  • get_by_user_id -方法名称
  • (int $id) -方法签名: ([[type] [parameter]<, ...>])
  • Bla-bla -一些可选的描述

更多有关@method

PS 虽然@method static在PhpStorm中工作正常(告诉IDE该方法是静态的),但实际的phpDocumentor工具可能尚未支持(还好吗?)(对不起,有一段时间没有使用它了)。


另外一种方法:(当然是在PhpStorm中)Settings | Inspections | PHP | Undefined | Undefined method --> Downgrade severity if __magic methods are present in class-它不会以任何方式帮助此类方法的代码完成,但是不会将那些魔术方法标记为“未定义方法”错误。


phpDocumentor有关使用正则表达式/部分名称作为@property/@method标记的票证(它如何对文档有用,以及在处理代码完成时对实际IDE的帮助很少):


2
谢谢,这看起来像是一个合理的建议,并且确实可以在phpStorm中使用,但是我有点讨厌在每个类的顶部写出@method的潜在几百行内容。您会看到get_by_ *方法可以由任何object参数添加,以通过指定参数获取该类型的对象。即使不包括get_by_的可能性_and_我会最终得到约1500@methods跨越140不同的类。有没有更通用的方式来提供文档?
罗伯·福雷斯特

否。必须专门声明所有魔术方法(这是以此方式进行记录的重点)-PHPDoc不理解部分名称(例如get_by_*(int $id))。对于IDE(代码检查,而不是完成!),您可以使用全部解决方案(禁用警告)。对于phpDocumentor(或替代工具)-我不知道任何解决方案(也许在那里,但我不知道)。您具有指向github的链接-提交新票证,并请求添加此类“部分名称”匹配功能-查看他们会说些什么(很可能会被拒绝)。如果将要实现,那么IDE以后也可能会拥有它。
LazyOne

github.com/phpDocumentor/phpDocumentor2/issues-但在发布您的票证之前,请检查是否不存在类似的票证。
LazyOne 2013年

感谢所有这些。目前有关于此的公开票,但似乎一切都变得安静了。我在这里发表了评论,我们将拭目以待。
罗伯·福雷斯特

2
仅供参考,phpDocumentor的票证(以便其他用户知道您在说什么票证;也将其添加到答案本身):github.com/phpDocumentor/phpDocumentor2/issues/689
LazyOne 2013年

4

与原始问题有关:

您也可以在phpstorm元文件中定义它。这是工厂方法(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();

这样,当魔术发生时,您不必对所有可能性进行文档阻止。

有一些文档以获取详细信息。


这不适用于__call。它也没有文档说明,并且是无效的PHP。PHPStorm仅在您具有静态定义的方法的地方提供支持,这些方法根据输入返回混合类型。
jgmjgm '18年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.