laravel进阶---repository仓库模式的使用【转】
前言
在自学了一段时间的laravel之后,小编自认为对于laravel这个框架还是基本可以掌握的。但是最近看了一份实验室的项目源码之后,小编感触良多。首先别人的代码总体上给人一种既简洁明了又高大上的感觉,代码看着简单但仔细去看,有的地方小编也一时看不懂。再反过来看小编自己的代码 (写的那是啥,简直惨不忍睹)。后来小编仔细的想了一下,为啥别人的代码可以写的如此的华丽呢,比对了我们两者的代码,小编发现我的数据逻辑处理的代码都放在了model层,有大量的重复代码。反观别人的代码,用了repository仓库模式存放数据逻辑处理的代码,代码的整体效果就闲得很简洁了。因此,小编决定来好好研究一下repository仓库模式,并且记录自己的学习过程,当做学习笔记。(大神请跳过,不喜勿喷)
1.为什么要用repository仓库模式
正如小编前面所说的,把处理数据逻辑的代码放在Controller或Model中都会让Controller和Model变得很臃肿,而且可读性会很差。此外如果每一个控制器或模型中都有对数据库的增删改查的话,代码不仅重复性高而且难以修改与测试。
2.如何实现repository仓库模式
在理解仓库模之前,我们先把基本的文件建立好,然后再理解一下。
步骤:创建接口类,创建仓库类,将两者绑定在一起
创建文件夹
在App目录下建立Repository文件下
在Repository下建立:
Interfaces文件夹
Repositories文件夹
分别创建接口类,和仓库类
如图:
创建控制器
代码如下:
TestInterface:在Interface中我们定义了我们必须要实现的方法,一般就是我们对数据库进行增删改查的代码。在接口类中我们可以清晰的看到我们有的所有方法。
TestRepository:在repository仓库类中我们继承了interface类用于实现具体的的方法。
Model:
看到这我们可以看到前面都是在实现interface 和repository的代码,那如何将两者联系到一起呢。
php artisan make:provider RepositoryServiceProvider
在provider下生成一个新的Service文件
在register方法中绑定接口类和仓库类,这样我们在控制器中声明一个TestRepository $ test后就可以用$ test调用访问仓库类中的方法
在
TestController:
当我们要进行数据库操作的时候,我们就可以在控制器中使用我们之前使用的仓库类。下面就是如何使用仓库类的问题了。我们可以看到
代码逻辑:通过路由访问控制器的index方法,在此之前控制器实现了自己的构造函数,并注入了仓库类的依赖,因此在index方法中我们可以访问TestRepository中的方法。
小编在学习的时候对下面的构造函数有所疑问
后来了解到在控制器中使用了这样一个构造函数来引入仓库了类。这就是所谓的依赖注入。至于依赖注入的理解,这里就不多说了,大家可以自行去了解一下。
依赖注入
服务提供者
服务容器
添加链接描述
运行结果:
小编在这是用了一个简单的例子,当我们的接口被多个类继承
我们还像这样
在自学了一段时间的laravel之后,小编自认为对于laravel这个框架还是基本可以掌握的。但是最近看了一份实验室的项目源码之后,小编感触良多。首先别人的代码总体上给人一种既简洁明了又高大上的感觉,代码看着简单但仔细去看,有的地方小编也一时看不懂。再反过来看小编自己的代码 (写的那是啥,简直惨不忍睹)。后来小编仔细的想了一下,为啥别人的代码可以写的如此的华丽呢,比对了我们两者的代码,小编发现我的数据逻辑处理的代码都放在了model层,有大量的重复代码。反观别人的代码,用了repository仓库模式存放数据逻辑处理的代码,代码的整体效果就闲得很简洁了。因此,小编决定来好好研究一下repository仓库模式,并且记录自己的学习过程,当做学习笔记。(大神请跳过,不喜勿喷)
1.为什么要用repository仓库模式
正如小编前面所说的,把处理数据逻辑的代码放在Controller或Model中都会让Controller和Model变得很臃肿,而且可读性会很差。此外如果每一个控制器或模型中都有对数据库的增删改查的话,代码不仅重复性高而且难以修改与测试。
2.如何实现repository仓库模式
在理解仓库模之前,我们先把基本的文件建立好,然后再理解一下。
步骤:创建接口类,创建仓库类,将两者绑定在一起
创建文件夹
在App目录下建立Repository文件下
在Repository下建立:
Interfaces文件夹
Repositories文件夹
分别创建接口类,和仓库类
如图:
创建控制器
代码如下:
TestInterface:在Interface中我们定义了我们必须要实现的方法,一般就是我们对数据库进行增删改查的代码。在接口类中我们可以清晰的看到我们有的所有方法。
<?php /** * Created by PhpStorm. * User: SWESWE * Date: 2019/7/3 * Time: 9:28 */ namespace App\Repository\Interfaces; interface TestInterface { public function findAll(); public function findOne($id); public function test(); }
TestRepository:在repository仓库类中我们继承了interface类用于实现具体的的方法。
<?php /** * Created by PhpStorm. * User: SWESWE * Date: 2019/7/3 * Time: 9:28 */ namespace App\Repository\Repositories; use App\Models\Test; use App\Repository\Interfaces\TestInterface; class TestRepository implements TestInterface { public function findOne($id) { // TODO: Implement findOne() method. return Test::find($id)->toArray(); } public function findAll() { // TODO: Implement findAll() method. return Test::all()->toArray(); } public function test(){ echo"接口测试类方法,绑定接口到实现"; } }
Model:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class test extends Model { // public $timestamps = false; protected $table = 'test'; }
看到这我们可以看到前面都是在实现interface 和repository的代码,那如何将两者联系到一起呢。
php artisan make:provider RepositoryServiceProvider
在provider下生成一个新的Service文件
在register方法中绑定接口类和仓库类,这样我们在控制器中声明一个TestRepository $ test后就可以用$ test调用访问仓库类中的方法
public function register() { //绑定接口和测试类 //测试models $this->app->bind( 'App\Repository\Interfaces\TestInterface', 'App\Repository\Repositories\TestRepository' ); }
在
的provider数组中添加App\Providers\RepositoryServiceProvider::class
TestController:
当我们要进行数据库操作的时候,我们就可以在控制器中使用我们之前使用的仓库类。下面就是如何使用仓库类的问题了。我们可以看到
<?php namespace App\Http\Controllers; use App\Repository\Interfaces\TestInterface; use App\Repository\Repositories\TestRepository2; use App\Repository\Repositories\TestRepository; class TestController extends Controller { // protected $test; public function __construct(TestInterface $test) //如果是声明的interface类 会自动认为是interface类绑定的第一个接口 { $this->test = $test; } // public function __construct(TestRepository2 $test)//如果是声明的interface类 会自动认为是interface类绑定的第一个接口 // { // $this->test = $test; // } // public function __construct(TestInterface $test)//如果是声明的interface类 会自动认为是interface类绑定的第一个接口 // { // $this->test = $test; // } // public function index(){ dump($this->test->findOne(1)); dump($this->test->findAll()); $this->test->test(); } }
代码逻辑:通过路由访问控制器的index方法,在此之前控制器实现了自己的构造函数,并注入了仓库类的依赖,因此在index方法中我们可以访问TestRepository中的方法。
小编在学习的时候对下面的构造函数有所疑问
后来了解到在控制器中使用了这样一个构造函数来引入仓库了类。这就是所谓的依赖注入。至于依赖注入的理解,这里就不多说了,大家可以自行去了解一下。
依赖注入
服务提供者
服务容器
添加链接描述
运行结果:
小编在这是用了一个简单的例子,当我们的接口被多个类继承
我们还像这样
绑定接口和仓库,那么我们在控制器中注入依赖时还像这样
那么我们就会发现TestController2返回的结果和TestController是一样的,但当我们把构造函数中的TestIntetface 换成TestRepository,TestRepository2就可以显示不同了。原因是用这样的
方法绑定多个仓库类会覆盖之前的绑定
这里我们用上下文绑定的方式来实现两个类使用同一个接口来实现接口和仓库类在服务容器中的绑定。
$this->app->when(TestController::class) ->needs(TestInterface::class) ->give(TestRepository::class); $this->app->when(TestController3::class) ->needs(TestInterface::class) ->give(TestRepository3::class);
很多时候,我们仓库类有很多而且又很多相同的方法,因此有的使用我们可以使用一个Baserepository来定义基本的方法,其他的仓库类继承他就好了。注册服务的时候我们像这样
$this->app->when(TestController2::class) ->needs(BaseRepository::class) ->give(TestRepository2::class);
————————————————
版权声明:本文为CSDN博主「SF梅花糕」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42265596/article/details/94630118