hyperf框架里的 make 和 new 有什么区别?

发布于 2022-09-12 23:46:27 字数 21 浏览 17 评论 0

求详细点的解答,至今没想清楚

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尽揽少女心 2022-09-19 23:46:27

不仅仅是 hyperf ,现代化一些的框架, Laravel、ThinkPHP 等,这些都有类似的方法,如 Laravel 的 app()app()->make() 等,其都归因为「容器」。

牛刀小试

举个简单的栗子,现在有一个需求,需要从数据库查询数据,需要一个 MySQLRepository 类,你可以在代码里直接写作:new MySQLRepository() 。就可以直接拿到 MySQLRepository 的实例,同样的 app(MySQLRepository::class) 或者 app()->make(MySQLRepository::class) ,也可以拿到这个 MySQLRepository 的实例。

如果只是简单的使用,看不出来有什么区别,都是 new 一个实例,倘若现在, MySQLRepository 不能满足需求了,你需要换到 MongoDBRepository,这时候,如果你使用 new 的方式创建的实例,你就需要把每个地方的 new MySQLRepository 替换为 new MongoDBRepository

这下工作量可就大了,但是如果使用了上面的「容器」,那就可以简单的在容器上添加绑定即可。

app()->bind(MySQLRepository::class, MongoDBRepository::class);

现在,之前写的 app(MySQLRepository::class) ,创建的实例实际上就成了 MongoDBRepository,这就是对容器最基本的使用。当然,这只是举例,实际业务中我们应该使用接口来完成 Repository 的定义。

依赖注入

依赖注入,其实才是这个带来的最大的好处。

举个栗子,常常能看到一些控制器方法中,有一个 Request 的注入,那你有没有想过,为什么我写了个类型,他就有 Request ,我不写他就没有呢?这就是 IoC(依赖注入容器) 在背后给我们做的。

它实现起来并不难,就是利用反射,来获取方法的参数,然后获得参数的类型,再使用容器或获取类型的实例(如果有绑定就返回绑定的),就这样,我们只写了一个简单的类型在那里,在使用的时候就成了实际的对象,这都是 IoC ,给我们做的的。

除此之外,还有更有趣的,绑定时我们还可以绑定一些初始化参数,比如,我们有一个 Ding 类,是一个钉钉机器人的类,一般情况下,我们都需要钉钉机器人的 SECRET 和 TOKEN,看起来像是下面这样。

$secert = config('ding.secert');
$token = config('ding.token');
$ding = new Ding($secert, $token);
$ding->send('Hi');

然后我们每次需要发送消息的时候,都需要来这样操作一次,当然,你可能会想,我可以封装一个方法然后完成这些不就好了,确实也可以,那么,这里用容器来做一下试试。

app()->bind(Ding::class, function(){
    $secert = config('ding.secert');
    $token = config('ding.token');
    return new Ding($secert, $token);
});

现在,这个 Ding 类就可以像在控制器方法里面那样,直接添加一个类型提示,就可以直接获得一个 Ding 实例,然后调用 send 方法了。

//...
class IndexController{
//...
    function index(Ding $ding){
        $ding->send('Hi');
    }
}

相比起封装一个函数,它更加容易被测试,因为我们可以随时替换容器的绑定,进行模拟。

自动依赖处理

依赖倒置,是一个非常好的实践,但是,可能会出现这种情况,
A 依赖 B,B 依赖 C, C 依赖 D, D 依赖 E ....

这时候如果我们想要一个 A 的对象,代码可能就会是这样 new A(new B(new C(new D())))

如果使用容器,就只需要 app(A::class),这样就能完成上面那一堆操作,是的,他会自动帮你递归解析依赖然后注入进去。

当然,实际情况可能比这些复杂,比如 B 可能是 A 的依赖项,也可能是 A2 的依赖项,而且在分别作为这两个的依赖项时,可能需要的参数还不一样,又或者,B 可能有出来依赖一个有类型的 A,还可能依赖一个常量值(基本值),这些都是有可能的,这时候又该怎么办?

这就涉及到了另一个知识点 上下文绑定,刚刚看了 Hyperf 的文档,没有提到这一块的内容,看了一下代码, hyperf/di 貌似也没有实现这个,那么可以参考一下 Laravel 文档中的 上下文绑定

使用 app 或者 app()->make() 的好处除了上述的外,还有一些 new 不太具备的,比如更加容易的测试。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文