茅塞顿开!2年了,我好像理解了Laravel的服务提供者

2022-06-14更新:服务绑定只是服务提供者的其中一个功能,还有其他的我还没有搞懂作者的设计思想

当我有一个发送短信的需求,我可以写一个接口类(App\Libraries\Interfaces\SmsInterface),必须实现send()方法。

Interface  SmsInterface 
{
    public function send(string $mobile, string $code):bool;
}

我现在要用到阿里云短信(App\Libraries\AliSms),这个时候我就将App\Libraries\Interfaces\SmsInterface绑定App\Libraries\AliSms,然后我在代码中调用短信类的时候直接依赖注入App\Libraries\Interfaces\SmsInterface

//绑定
public function register()
{
    $this->app->singleton(SmsInterface::class, function ($app) {
        return new AliSms();
    });
}
class SmsController
{
    //业务代码,发送短信
    public function send(SmsInterface $sms, Request $request)
    {
        $sms->send($request->mobile, '1234');
    }
}

如果后期要改成腾讯云短信,我就可以写一个TxSms实现SmsInterface接口,然后在服务提供者中把SmsInterface绑定TxSms,就不需要在代码中把所有的类都修改一遍了。

public function register()
{
    $this->app->singleton(SmsInterface::class, function ($app) {
        return new TxSms();
    });
}

我认为我的理解是没有问题的,用laravel2年了,算是终于明白服务提供者了,网上很多教程我感觉都是翻译的国外的,狗屁不通,用短信的例子讲一下就明白了!

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 48
Cooper

恭喜你,理解没错。

3个月前 评论
laravel_peng

言简意赅!我也理解了~

3个月前 评论

你这个理解的是laravel的ioc,不是服务提供者[dog]

3个月前 评论
勇敢的心 (楼主) 3个月前
deatil (作者) 3个月前
勇敢的心 (楼主) 3个月前
deatil (作者) 3个月前
勇敢的心 (楼主) 3个月前
勇敢的心 (楼主) 3个月前
勇敢的心 (楼主) 3个月前
deatil (作者) 3个月前

整体理解的没问题,但你说的场景更准确的说法是,绑定是属于服务提供者的其中一种具体应用,这里引申出的概念就是 服务提供者可以包含绑定,但绑定不等于服务提供者。

我觉得会出现服务提供者这样的东西,应该是为了解耦。

参考资料 服务提供者《Laravel 9 中文文档》

3个月前 评论

文档说的很清晰, 你这里注册容器绑定只是服务提供者可以做的其中一项

3个月前 评论

楼上说的对,你把 A(实例) 绑定到 B(接口),其实这只是做了一件事情。然而在 service provider 中,你可以做很多事情,比如注册宏、设定类常量等等,综合来说,就是你可以利用service provider 来做自己想做的事情(例如把实例绑定到接口)。

但是 "service provider" 不等于 "A绑定B这个动作"。

3个月前 评论

如上面所说,这是 “服务容器” 的内容,绑定到容器和从容器解析,这只是服务提供者可以做的冰山一角。

服务提供者更像是一个清单文件,具体的作用可以见官方文档中的“扩展包开发”章节。

3个月前 评论

你这个就是把类的实现注入到容器而已 可以在任何地方做 你真正应该想的是 为啥需要laravel 推荐在服务提供者里面注入 别的框架YII他们是什么时候 注入到容器的

3个月前 评论
勇敢的心 (楼主) 3个月前

我的理解: 接口解决的是代码复用的问题; 服务提供者解决的是代码解耦的问题;

你这个实现主要就是用了接口来避免其他代码对这部分代码实现的依赖(也就是你这段代码改了,其他代码也不需要修改); 服务提供者我理解的是容器的管理员,把第三方服务封装起来,给其他代码拿来即用,provider把服务的初始化,配置都处理好了,只需要引用自己需要的功能即可。 比如例子里短信服务就是在provider里面配置好相关的参数,外部就只提供业务相关的接口。

3个月前 评论
勇敢的心 (楼主) 3个月前
redfish (作者) 3个月前
勇敢的心 (楼主) 3个月前

这是绑定接口到实现吧,服务提供者【provider】就是一个boot和一个register组成的类,boot是实例化之后的处理,我的理解就是把服务提供者放到app这个容器【数组】里面,注册【register】一个别名【下标】,然后app这个容器在laravel整个生命周期是全局的,他会处理服务提供者里面的依赖关系,你这就相当于把这个别名【下标】换了一个实现,如果是用容器解析出来的类,在register这里换了之后整个生命周期都会跟着改变

3个月前 评论

服务提供者

file

继承这个类的,都是服务提供者。

注册服务 用的

楼主说的, 只是 服务器提供者 里面用 契约 (接口绑定)。

正常情况

 $this->app->singleton('sms', function ($app) {
        return new AliSms();
    });

后面改成: 
$this->app->singleton('sms', function ($app) {
        return new TxSms();
    });

契约 的话,开发懒着写接口,看爱好和场景了。

我并不认为lar核心是什么高大上的东西 还不如俗气点

3个月前 评论
勇敢的心 (楼主) 3个月前
lyxxxh (作者) 3个月前
勇敢的心 (楼主) 3个月前
lyxxxh (作者) 3个月前
xgping 2个月前

github.com/whitexiong/faker-larave... 其实自己手写的,说实话没必要死磕这些概念很复杂原理很简单。自己推到一遍是不是然后再工作中理解

3个月前 评论
勇敢的心 (楼主) 3个月前

其实本质上就是把类绑定到Ioc服务容器中

3个月前 评论
勇敢的心 (楼主) 3个月前
oliver-l (作者) 3个月前

服务提供者应该是指绑定某个对象或抽象至容器中,每次我们访问laravel时,容器就会运行所有provider::boot方法,把里面注册的东西全部挂到容器缓存中,当我们使用app()或$this->app['instance']时,就会直接从容器中去取,避免二次实例化

3个月前 评论
勇敢的心 (楼主) 3个月前

服务提供者最大的一个作用就是方便拓展,尤其在 composer 包开发的时候,通过 bootregister 方法,可以将composer 包的 路由 和 command 命令注册进去。所以可以基于服务提供者做出 laravel-admin, dcat-admin 这种项目。

同理在多人开发项目过程中,我们可以建四个业务逻辑目录,主程序只加载4个服务提供者。让四个开发者去完成对应的不同模块,在各自模块他们建立自己路由,控制器,中间件。当有一天其中一个业务逻辑砍掉的时候,我只需要在主程序注释掉这个业务模块服务提供者即可。

3个月前 评论
勇敢的心 (楼主) 3个月前
勇敢的心 (楼主) 3个月前
喝卵形 (作者) 3个月前
喝卵形 (作者) 3个月前
Cooper 3个月前
勇敢的心 (楼主) 3个月前

楼主的表述,贴的代码,只是在讲面向对象。

3个月前 评论
勇敢的心 (楼主) 3个月前

看代码,是在 服务提供者 里面使用 服务容器 实现了 依赖注入服务提供者 的意思要更广一些。

其中核心的就是 registerboot 方法(我认为理解这两个方法的区别就可以),以及延迟加载提供者。

register 是注册方法,在所有的 服务提供者 被注册以前执行,主要是注册和绑定一些服务。

boot 是引导方法,在所有的 服务提供者 被注册以后执行,进行一些业务逻辑。

3个月前 评论
pndx

mark

3个月前 评论
勇敢的心 (楼主) 3个月前
pndx (作者) 3个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!