先看一篇好的介绍:
前言
刚开始看 laravel 服务容器、契约、服务提供器的确生涩难懂,不单单是概念繁多,而且实际的 demo 很难找(找是找到了,但难用啊),最后就隔一段时间看一遍,大概个十来遍,还真给看出个门道,废话少说上代码。
准备阶段
首先声明一下我的测试环境
php 7.2.4
laravel 5.6
1. 创建新项目(composer)
在你的项目目录命令行运行:
composer create-project laravel/laravel laravelapp --prefer-dist
2. 创建服务提供器
生成文件位于:项目 /app/Providers/TestServiceProvider
php artisan make:provider TestServiceProvider
同时修改配置文件 config/app.php,在 providers 数组中追加该服务提供器
'providers' => [
App\Providers\TestServiceProvider::class,
],
3. 创建自己的工作目录(xiaocai)
我的工作目录在:项目 /app/Xiaocai 目录下
// 目录结构
|---app
|---Xiaocai
|---Test
|---DemoInterface.php
|---DemoProvider.php
|---DemoProvider2.php
写到这里你可能问我的工作目录下三个文件干什么用呢?不要着急,接下来我们逐个创建文件并进行讲解。
1:DemoInterface.php【接口文件】这个就是 laravel 中提到的 Contracts(契约),使用接口(契约)的原因官方也给了说明:低耦合和简单性,文件内容如下:
<?php
namespace App\Xiaocai\Test;
interface DemoInterface
{
function demo1();
function demo2();
}
接口中只简单定义两个测试方法,记住带上命名空间 App\Xiaocai\Test,这个很重要;
2:DemoProvider.php【接口实现类】,这个官方并没有特别说明,当然,有了接口当然会有对应的实现类去实现接口中的方法
文件内容如下:
<?php
namespace App\Xiaocai\Test;
class DemoProvider implements DemoInterface
{
public function demo1()
{
return 'demo1';
}
public function demo2()
{
return 'demo2';
}
}
对于这个实现类,我是这样理解的,laravel 中的契约(接口)通过规定好方法名称,这样,第三方扩展包在想要实现这些契约方法的时候,必然要受到契约提供的方法的约束,防止滥用,使用户在使用 laravel 基础上的扩展包的时候,不必要再去了解底层代码逻辑,方法都是定义好的,尽管不同的包处理的逻辑不同,但是对于用户来说,都是调用的同一个方法,对于如何选择到底使用哪个实现类,我们也准备好了 DemoProvider2.php 类,他是 DemoInterface.php 的第二种实现方法。
3:DemoProvider2.php【接口实现类 2】内容如下
<?php
namespace App\Xiaocai\Test;
class DemoProvider2 implements DemoInterface
{
public function demo1()
{
return 'demo1的第二种实现';
}
public function demo2()
{
return 'demo2的第二种实现';
}
}
4. 创建测试控制器
命令行运行:
php artisan make:controller TestController
5. 添加路由
为测试控制器添加一个测试路由,修改项目 /routes/web.php 文件,追加代码如下:
Route::get('/test', 'TestController@index');
6. 修改服务提供器文件(TestServiceProvider)
这里是重点!这里是重点!这里是重点!重要的事情我只说三遍
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Xiaocai\Test\DemoInterface;
use App\Xiaocai\Test\DemoProvider;
use App\Xiaocai\Test\DemoProvider2;
class TestServiceProvider extends ServiceProvider
{
public function boot()
{
}
public function register()
{
$this->app->bind(DemoInterface::class, DemoProvider2::class);
}
}
在这里就可以对想要使用的实现接口(契约)类进行选择,$this->app->bind (arg1, arg2); 参数 1 代表接口类,参数 2 代表要使用的接口实现类,你可以在这里进行切换选择实现类,切换之后如何验证呢?
验证
修改 TestController 文件
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Xiaocai\Test\DemoInterface;//注意引用的是接口文件,并非实现类
class TestController extends Controller
{
public function index(DemoInterface $demo)
{
dd($demo->demo1());
}
}
此时浏览器输出接口不出意外的话应该是这样的:
我们不妨修改一下实现类,在 TestServiceProvider 文件中修改如下:
$this->app->bind(DemoInterface::class, DemoProvider::class);
//$this->app->bind(DemoInterface::class, DemoProvider2::class);
此时再运行,如下:
总结
如此一来,切换实现的方法是不是很简单,只需要在服务提供器中修改即可,果真是低耦合。如果文章中出现什么纰漏欢迎指出,防止祸害他人,如果觉得对您有帮助的话,点个赞支持一下吧。
结语
另外 Xiaocai 工作目录是测试用的,当然如果做项目的话,你也可以把你的代码上传到 composer,这样通过 composer 直接引入到 vendor 目录下,通过 composer 的自动加载机制,这样是不是更能提高你的效率呢。
————————————————
原文作者:xiaocailc
转自链接:https://learnku.com/articles/17638
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。
总结:
刚看的时候不了解一个类我直接use就行了,为什么还要去注册一次。现在了解了。比如:我a类和b类都继承了c接口。我现在在服务提供者里注册a类。那么通过c调用的都是a类的方法。但如果我之后想全部换成b类。则直接在注册这里把a类改成b类就好了。最明显的就是我把缓存从最初的mem改成redis.只要实现的是同一个缓存接口。就只需要改服务提供者这里的注册。