laravel中的服务提供者有什么作用?

pengzeyun
  • 1
新手上路,请多包涵

第一步:定义契约接口类

<?php
namespace App\Contracts;
interface TestContract
{
    public function say($info):string; 
}

第二步:定义子类服务实现接口

<?php
namespace App\Services;
use App\Contracts\TestContract;
class TestService implements TestContract
{
    public function say($info):string
    {
        dd($info);
    }
}

第三步:创建服务提供者

<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Services\TestService;
class TestServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind('App\Contracts\TestContract', function(){
            return new TestService();
        });
    }
    public function boot()
    {
    }
}

第四步:注册服务提供者

// app\config\app.php
<?php
    'providers' => [
        # 此处省略其它内容
        App\Providers\TestServiceProvider::class,
    ],

第五步:测试服务提供者

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Contracts\TestContract;
class TestController extends Controller
{
    public function test(TestContract $test)
    {
        $test->say('test');
    }
}

以上内容是按照laravel文档创建的,但是测试的时候,第三步和第四步可有可无,不注册服务提供者,在第五步的控制器中也能调用say()方法;那请问这个服务提供者到底有什么作用啊??

回复
阅读 383
3 个回答

服务提供者更多的是用于对于 Laravel 框架的扩展,因为在日常的项目开发过程中,我们总会遇到一些,通用性的内容,比如跨域处理、文件上传、消息推送、发送短信等,这些可以独立于项目的组件。

如果按照传统的不分离的形式,你就需要在 app 创建一个目录来保存这些内容,并且,这些可能都会有各自的配置项,那你就还需要创建对应的配置文件,现在你只需要调用 App 命令空间下对应的类,就可以调用这些服务。

但是,如果你要新建一个项目,你现在就只有把当前的代码拷贝一份出去(别忘了配置项),到新项目,然后复用,这是最理想的状态。

但是你想一下,如果因为某个功能,你修改了这个类,然后其他项目又用不到,那拷贝的时候,可能还要清理掉这些内容,又或者,这个类里面有个 BUG ,你就要修改每一个项目。

而现代化开发,讲究的就是一个复用,提高代码的复用性,减少重复(CV)工作。

现在换个方式,你可以创建一个 composer 包,然后把所有代码都搬到这个包里面去,包括配置项。然后把这个 composer 包发布到仓库去(可以自建、也可以使用公共仓库),紧接着,你就可以使用 composer require 来安装你新提取出去的这个包了。

安装完成后,你的新包可能并不能完好的工作,比如提到的契约接口注册、配置项获取等。因为这会儿他只是一个普通的包。

现在,做一件事情,创建一个 ServiceProvider ,就把所有的资产(契约接口注册、配置项注册、本地化、模板)等进行注册。

然后,你还需要在 laravel 中去注册这个 ServiceProvider ,然后你得扩展包里面的内容就可以正常工作了,以后新建项目的时候,只需要 composer require 一下这个包,然后注册一下 ServiceProvider 就可以了,如果某个类有 BUG ,你现在只需要修改这个包的代码,在其他项目更新一下,即可拿到最新的代码。

注:自 laravel 5.5 起,composer 包可以配置自动注册发现服务提供者,不再需要手动去注册,变得更爽了

说到这里,或许你能理解一些,但是这大部分的功劳仍然归功于 composer ,而服务提供者(ServiceProvider) 更像是一个清单文件,来告诉 Laravel ,应该怎么处理这些资源,或者启动哪些服务。

简单的项目中,一般并不太需要自行创建 ServiceProdiver ,因为你可以简单的在自带的 AppServiceProvier 中编写你的代码,创建单独的服务提供者可以为了以后扩展打下基础。

你上面说到的契约接口注册绑定,只是服务提供者的冰山一角,可以参考文档中关于 扩展包开发 章节的内容。

关于为什么需要接口绑定,可以继续查阅有关:依赖注入、依赖倒置 方面的知识。

我理解这两个概念,倒不会纠结你这个输出结果,我会从概念的含义和场景来解释。

契约:是一组接口(interface),它们由框架提供并定义了核心服务。场景:mem切换成redis
,感觉契约类似工厂模式,方便对象的切换

服务提供者:我理解为管理服务的,注册(绑定)服务。用容器来实现,也就是依赖注入。用来解耦的。

你的第一、二步是契约,第三步是服务提供者的绑定(不是契约),第四步是契约和服务提供者都会用到的配置,第五步是一个控制器的依赖注入。如果第五步使用app()->make的方式来注入,三、四可能就需要了。感觉把契约、服务提供者、依赖注入混在一起了,我觉得分开来写比较好

最后,我也是初学者,也不知道对不对

把provider理解成插件的入口.

你这儿没效果是因为 laravel 创建对象时, 默认就是直接new,
app()->make('全\类名') 相当于 new 全\类名,
如果你的类有个性化初始化需求, 那只能在通过provider的register设置.
比如要设置某个属性, new TestService()->setXXX()

你知道吗?

宣传栏