4

尽管代码示例来自 Laravel,但这不是 Laravel 问题!

所以我有这部分代码

class MacroServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Collection::macro('method_name', function () {
            return $this->map(function ($item) {
                //...do something;
            });
        });
    }
}

问题是$this不属于,MacroServiceProviderCollection我的 IDE 和 phpstan 显示我的错误,当然。

编辑:问题不清楚。IDE 认为这$this只是MacroServiceProviderCollection. 所以当它被执行时$this将是Collection. 我想要实现的是指示代码验证器 $this 内部回调是Collection实例。

是否可以注释$this并告诉它属于Collection实例?

PS PHP 版本是 7.3 IDE 是 PHPStorm 但我认为没关系。

PPS 代码工作得很好。这只是关于 phpstan 验证。

4

2 回答 2

3

最简单的解决方案是支持一个 docblock $this- 它确实适用于 PhpStorm,不确定 phpstan:

class MacroServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Collection::macro('method_name', function () {
            /** @var Collection $this */
            return $this->map(function ($item) {
                //...do something;
            });
        });
    }
}

但是请记住,对该猴子修补的 Collection 方法的任何调用都会导致相同的问题 - IDE 和分析器都不会知道它的存在。我个人会避免这些策略 - 我宁愿使用组合将 Collection 嵌入到其他对象 - 无论是您的自定义集合类还是需要您的集合的某个容器。但这当然不是 Laravel 的做事方式。

更新。为 phpstan 找到了一些不错的包装器 - larastan - “支持 Laravel 的美丽魔法”。它可能会有所帮助。

于 2019-03-17T11:00:04.840 回答
0

向 IDE 提供提示的另一种方法是创建一个方法存根文件。对于在 Collection 类上创建的宏,它可能看起来与此类似:

<?php


namespace Illuminate\Support{ 

    /**
     * 
     *
     */ 
    class Collection{
        /**
         *
         *
         * @return Collection
         */ 
        public function method_name() {}
    }
}

这是laravel-ide-helper等软件包用来向 IDE 提供有关 Laravel 中许多动态方法调用和依赖注入的提示的技术之一。

作为参考,这里是_ide_helper.php它生成的文件的完整示例,取自自述文件:https ://gist.github.com/barryvdh/5227822

根据标题,它至少应该适用于 Netbeans、PhpStorm 和 Sublime Text 2 CodeIntel。

充满方法存根的文件是像 PhpStorm 这样的 IDE 如何为编译到 PHP 运行时的标准库提供代码提示 (IntelliSense)。不同之处在于这些存根位于 IDE 安装目录中的某个位置,而不是您的项目目录中。

于 2019-03-17T14:33:42.500 回答