【问题标题】:PhpStorm type-hinting for factories?工厂的 PhpStorm 类型提示?
【发布时间】:2013-07-14 01:16:13
【问题描述】:

我的代码或多或少是这样的:

class Foo {
    public static function factory($str) {
        $class = "Foo_" . $str;
        return new $class;
    }
}
class Foo_Bar {
    public function razzle() {
        print "Foo_Bar->baz() was called";
    }
}

$Obj = Foo::factory('Bar');

我希望 PhpStorm 了解 $Obj 是一个 Foo_Bar 对象,例如,如果我输入 $Obj->razrazzle() 将显示为自动完成。

有没有办法得到这个?告诉 PhpStorm 函数 Foo::factory($str) 返回一个 Foo_$str 类型的对象?我的猜测是答案是否定的。

【问题讨论】:

    标签: factory phpstorm type-hinting


    【解决方案1】:

    据我所知,您无法让 PHPStorm 了解 Foo 发出的内容,因为它是动态的。但是,您可以肯定地告诉 PHPStorm 您的 $Obj 变量是什么,方法是在其上方添加 doc 注释,如下所示:

    /** @var Foo_Bar $Obj */
    $Obj = Foo::factory('Bar');
    

    【讨论】:

    • 这让 PhpStorm 知道 $Obj 的数据类型,但我想让 PhpStorm 知道 Foo::factory() 的返回数据类型——我不想每次都使用 PhpDoc @var使用工厂,这只是一个丑陋的黑客。 LazyOne 的回复听起来很有希望,但我似乎无法让它发挥作用;我怀疑我错过了一步。
    • @hobbit.trap “这只是一个丑陋的黑客行为”——事实并非如此。 PHPDoc 本身没有提供动态返回类型的机制(从实际字符串参数值构建)。如果它不在实际的 Doc 标准中(用于代码提示),你为什么期望它会神奇地工作?
    • @LazyOne 正如您所注意到的,PHPDoc 没有内置这种机制。当然,任何基于 PHPDoc 的解决方案都必然是一个 hack。但我不是在寻找 PHPDoc 解决方案,而是在寻找任何 PhpStorm 解决方案——您在上面提供了,非常感谢!
    【解决方案2】:

    是的,如果您的工厂是静态方法,您可以这样做。对于您提供的示例,它应该可以正常工作。

    更多细节和一些基本的例子可以在这里找到:http://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Advanced+Metadata

    【讨论】:

    • 也许我做错了什么,但它似乎对我不起作用。我正在使用 PhpStorm 6.0.3。我在一个新的空项目中创建了以下两个文件:pastie.org/8146899,但在 ``$x->...` 上我没有得到任何类型的自动完成功能
    • 为我工作。 1) 带有元数据的文件必须命名为.phpstorm.meta.php; 2) 它不会立即被拾取——关闭并重新打开项目(在项目加载时搜索此类文件;一旦找到文件,应立即拾取对它的更改)——此行为已修复v7.
    • 谢谢!我没有意识到这个名字是必需的,它现在很好用。
    • @Sorcy 根据 LazyOne 链接的页面,似乎静态调用键现在可用于几个月前的静态和实例方法调用。
    • @AdrianGünter Nice - 我必须在我们的一个项目中尝试一下。
    【解决方案3】:

    您应该使用适用于动态和静态调用的 phpstorm 元数据。

    class Foo {
        public function factory($str) {
            $class = "Foo_" . $str;
            return new $class();
        }
    }
    class Foo_Bar {
        public function baz() {
            print "Foo_Bar->baz() was called";
        }
    }
    
    $Obj = Foo->factory('Bar');
    $Obj->baz();  
    

    在您的项目根目录中创建一个文件并将其命名为.phpstorm.meta.php

    <?php
    
    namespace PHPSTORM_META {
        $STATIC_METHOD_TYPES = [
            \Foo::factory('') => [
                "Bar" instanceof \Foo_Bar,
            ],
        ];
    }
    

    感谢@LazyOne 提供链接。

    【讨论】:

    • 如此尴尬和麻烦。还不如直接在你的类/方法中使用/* @return ClassA|ClassB|ClassC */,而不必接触元数据文件,所有这些文件都是隐藏的,很难移植,也没有提交到 repo。
    • @ahnbizcad 它对于非平凡的方法非常强大。此外,该文件不需要驻留在您的存储库中。我把我的放在另一个目录中,并将该目录添加到我的项目中。
    【解决方案4】:

    对我有用的一种方法是在“或”列表中明确列出工厂可能吐出的所有可能的类。

    /**
     * @param $str
     * @return Foo_Bar | Foo_Cad | Foo_Dad
     */
    class Foo {
        public static function factory($str) {
            $class = "Foo_" . $str;
            return new $class;
        }
    }
    

    但这确实意味着实例/对象上的所有方法类型提示都将具有所有列出的类的联合。

    并不完美,但总比没有好,也比每次出现/* @var ClassA */都要写多次要好。

    【讨论】:

      【解决方案5】:

      一种方法是在“或”列表中明确列出工厂可能吐出的所有可能的类。

      <!-- language: lang-php -->
      
      /**
       * @param $str
       * @return Foo_Bar | Foo_Baz | Foo_Cad
       */
      class Foo {
          public static function factory($str) {
              $class = "Foo_" . $str;
              return new $class;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-26
        • 2019-03-08
        • 2015-05-23
        • 2014-08-29
        • 2014-09-14
        • 2015-12-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多