【问题标题】:How to tell phpDoc a string is a class name?如何告诉phpDoc一个字符串是一个类名?
【发布时间】:2014-12-21 05:21:33
【问题描述】:

我经常给对象提供不需要初始化对象的静态方法和属性。例如:

class SomeObject {
    public function __construct($object_id) {
        $this->loadProperties($object_id);
    }

    public static function getSomeStaticString() {
        return "some static string";
    }
}

现在我们对这些对象进行子类化,并拥有某种控制器,该控制器在对象尚未初始化的某些情况下返回对象类字符串。例如:

class SomeObjectController {
    public function getSomeObjectWithTheseProperties(array $properties) {
        if($properties[0] === "somevalue") {
            if($properties[1] === "someothervalue") {
                return SomeSubclassObject::class;
            }

            return SomeObject::class;
        }

        return NULL;
    }
}

有时我可能想在不实际初始化对象的情况下调用静态函数SomeObject::getSomeStaticString()(因为这将涉及不需要的数据库提取)。例如:

$controller = new SomeObjectController;
$properties = array("somevalue", "someothervalue");
$object_class = $controller->getSomeObjectWithTheseProperties($properties);

echo $object_class::getSomeStaticString();

问题:我能否以某种方式告诉 PhpStorm,最好是通过 phpDoc,$object_classSomeObject 的子类的类字符串?

如果我告诉我的 IDE 它是一个字符串,它会通知我 getSomeStaticString() 是一个无效的方法。另一方面,如果我告诉我的 IDE 它是 SomeObject 的一个实例,它认为我可以访问常规的非静态方法和属性,而我不能。

【问题讨论】:

    标签: php phpstorm phpdoc


    【解决方案1】:

    PHPStan 为此使用class-string PHPDoc 类型。 PHPStorm 自 2020.3 以来一直支持它,但在 2021.2 添加对泛型的支持后,它似乎可以正常工作(所有自动完成功能都可用)。

    在您的情况下,返回类型注释将是 @return class-string<SomeObject>

    【讨论】:

    • 仅供参考:PhpStorm 2020.3 将拥有自己的 PHPStan/Psalm 集成插件:blog.jetbrains.com/phpstorm/2020/10/phpstorm-2020-3-eap-2 并且您引用的该插件可能不再适用于较新的 IDE 版本(部分相关评论: youtrack.jetbrains.com/issue/…)
    • @LazyOne 2021.3 仍然不是一个好的实现,并且在 intellij 中也不可用。
    • @stevemoretz 特别是哪个插件? Psalm SupportPHPStan Support 插件都被标记为与 IntelliJ IDEA Ultimate 兼容(它们与 PhpStorm 捆绑在一起,但需要在 IntelliJ 中手动安装)。
    • @stevemoretz 是的,它们还不支持所有功能。 Tickets can be seen here
    • @LazyOne 这是一个非常好的链接,实际上我发现 JetBrains 有一个名为 Psalm Suport 的插件,它也可以安装在 Intellij 上!太好了,但是上面答案中的这个插件不再起作用了,所以谢谢!您可以将您的解决方案作为答案发送,我会投赞成票。
    【解决方案2】:
    /** @var SomeObject $object_class */
    $object_class = $controller->getSomeObjectWithTheseProperties($properties);
    

    抱歉,没有其他方法可以判断它是SomeObject 的实例。

    ...如果我告诉我的 IDE 它是 SomeObject 的一个实例,它认为我可以访问常规的非静态方法和属性,而我不能。

    所以?只是不要访问非静态方法和属性。


    2021-10-26 更新: 自 v2020.3 起,PhpStorm 捆绑了 Psalm SupportPHPStan Support 插件。它们支持这些工具支持的大多数语法/类型(您可以check PhpStorm Issue Tracker here 获取这些插件的所有票证(已解决且仍在等待中))。

    通过这些工具,您可以使用class-string 伪类型:

    【讨论】:

    • 害怕我会被指向@var SomeObject。这就是我所得到的。我觉得把字符串称为对象很脏。
    • 问题是:PHPDoc 或 PhpStorm 都不支持“这是一个代表类的字符串”类型的类型提示。如果你想 - 使用 string 而不是 SomeObject - 现在感觉更干净了吗?事情是 - 这不会使警告消失。您总是可以禁止对该行发出警告..但这实际上是错误的方式/更脏。
    • 鉴于上述对话,我还建议您在该文档注释中添加说明,说明这是对类的引用,而不是实际实例。它可以帮助稍后阅读您的代码的团队成员。我为考古道歉。我只是把这个留在这里,以防下一个人少了几美分。 ;)
    • 好吧..如果有人只需要一个警告抑制......那么他/她可以使用一些保护逻辑,例如用if (method_exist(...) {...} 调用包围——IDE 现在理解它。它将有助于不显示警告..但可能仍无法提供代码完成帮助。
    【解决方案3】:

    如果您想要完美的类型提示,您可以创建一个仅列出类的静态方法(和属性)的接口,并将该接口用作从SomeObjectController::getSomeObjectWithTheseProperties() 返回的类名字符串的类型提示。

    它增加了维护开销以确保接口和类保持同步,但如果您需要这些类型提示才能正常工作,这就是方法。

    【讨论】:

    • 请分享更多细节。该方法的 phpDoc 注释会是什么样子?
    【解决方案4】:

    您也可以使用此解决方法:

    /**
     * @return string|SomeObject
     */
    public function getSomeObjectClass()
    {
        return SomeObject::class;
    }
    

    【讨论】:

    • 请在您的答案中添加一些解释,以便其他人可以从中学习。给定的方法永远不会返回 SomeObject 的实例,所以对我来说这看起来不正确
    猜你喜欢
    • 2022-08-16
    • 1970-01-01
    • 2021-10-21
    • 2018-08-16
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多