Laravel与Repository Pattern(仓库模式)
为什么要学习Repository Pattern(仓库模式)
Repository 模式主要思想是建立一个数据操作代理层,把controller里的数据操作剥离出来,这样做有几个好处:
- 把数据处理逻辑分离使得代码更容易维护
- 数据处理逻辑和业务逻辑分离,可以对这两个代码分别进行测试
- 减少代码重复
- 降低代码出错的几率
- 让controller代码的可读性大大提高
然而,据很多同学反应,这一部分很难学。确实,要独立一个操作层出来,确实会增加大量代码,非常繁琐。如果你是小项目,未必需要使用这一模式。但如果是4-5年以上的复杂大型项目,这种模式的好处就比较明显了。
如果你是纯新手,建议你暂时不要往下看,先把laravel用得比较熟练后再回来学习。
学习Repository Pattern的意义不只是为了使用它,更会让你深入思考框架的分层思想,你开始不仅关注怎么使用一个框架,还会想了解怎样设计一个框架,也许会成为你往高阶段编程的入口。
什么是Repository Pattern
虽然说设计模式和语言及框架无关,但是脱离了语言及框架,我们很难理解,所以我们还是在laravel的语境下来学习吧:
public function index()
{
$posts = Post::whereIn('category_id',[,])->where('is_draft',)->orderBy('created_at', 'desc')->take()->get();
return view('front.index',compact('posts'));
}
以上是典型的Eloquent数据查询代码,如果你编程经验丰富,你会发现这种代码在控制器里到处都是,而且有很多是重复的,可读性很差;我们的目标是把它精简:
仔细观察
Post::whereIn('category_id',[1,2])->where('is_draft',0)->orderBy('created_at', 'desc')->take(5)->get();
其实它由3部分组成,第一是Post,数据模型;第二个是whereIn('category_id',[1,2])->where('is_draft',0)->orderBy('created_at', 'desc')->take(5),数据操作条件;第三个是get(),数据获取的方法;
我们知道,Eloquent里有个Query Scope,可以用来把第二部分,也就是查询条件精简。所以,在使用了Query Scope后,我们可以把精简成:
Post::ofCategory([1,2])->isDraft()->orderBy('created_at', 'desc')->take(5)->get();
咋一看上去,好像也没怎么精简啊,但实际上你已经实现代码解耦和复用了,比如说isDraft(), 这个代码可以到处用,而不用担心耦合问题。
精简程度和你的逻辑抽象程度有关,比如说你完全可以写成:
Post::findPosts([1,2],0,'desc',5)->get();
在轻型项目中,强烈推荐使用Query Scope,这是一种良好的编程习惯。
在更复杂的项目中,Query Scope就不够用了,因为它和数据模型还是一种强耦合,Repository Pattern就是要把第一,第二,第三部分全部解耦;
说到解耦,我们在Laravel的文档攻略中讲过,第一神器就是PHP中的接口(Interface),下面来看例子:
第一步——建立文件夹
- app
- Repositories
- Interfaces
- Implements
Interfaces里面用来放接口,Implements用来放接口的实现;
第二步——建立一个接口
在上面的Interfaces目录新建一个文件PostInterface.php:
namespace App\Repositories\Interfaces;
Interface PostInterface{
public function findPosts(Array $cat_id,$is_draft,$order,$take){
}
}
第三步——建立一个接口对应的实现
在上面的Implements目录新建一个文件PostRepository.php:
namespace App\Repositories\Implements;
use Post;
class PostRepository Implements PostInterface{
public function findPosts(Array $cat_id,$is_draft,$order,$take){
$query = Post::whereIn('category_id',$cat_id)->where('is_draft',$is_draft)->orderBy('created_at', $order)->take($take)->get();
return $query;
}
}
看这里,很明显,仓库指的就是一个仓库接口的实现;这里定义你的业务逻辑;
第四步——在ServiceProvider中绑定接口
打开app/Providers/AppServiceProvider, 在register()加入代码:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
}
public function register()
{
$this->app->bind('App\Repositories\Interfaces\PostInterface', 'App\Repositories\Implements\PostRepository');
}
}
我们知道,ServiceProvider是Laravel IOC容器实现动态换接口实现的地方,所以我们在这里绑定一下,这样我们在使用的时候,不直接使用接口实现,而是用ioc容器解析接口,它会帮你自动找到对应好的实现。 这就意味着,以后需要更换实现,可以在这里更换;
第五步——使用仓库
回到我们的controller里来:
use App\Repositories\Interfaces\PostInterface;
class PostController extends BaseController{
public function __construct(PostInterface $post){
$this->postRepo = $post;
}
public function index(){
$this->postRepo->findPosts([,],,'desc',);
}
}
这样你看,第一,我们的业务逻辑变得非常精简,完全不用管查询;第二,现实了数据查询部分的解耦;
到这里,有同学就会问了,一开始说好的三个部分解耦呢,你这里只实现了第二部分啊;
确实,为了最快让大家明白什么是Repository,我把第一和第二部分的解耦省略了,我们放到这篇文章的系列后续讲。
你或许还有不少疑惑,我费那么大劲,写成最后这个样子,好像也没什么区别啊。聪明的同学可能想到一点,如果采用Repository Pattern的话,是不是意味着以后我可以先在controller里写成$this->postRepo->findPosts([1,2],0,'desc',5); 具体的查询逻辑先不写,然后我快速先把 整个应用的业务逻辑先跑一遍,然后再回头一个一个写接口实现来支持业务逻辑;(哇擦,太NB了,妈妈再也不用担心SB客户/PM改变需求了);
恭喜,你已经进入高级编程里说的DDD(Domain Driven Design 领域驱动设计)大门了,事实上,整个Laravel框架的核心架构就是这样干的,IOC+接口,我们会在后续系列文章里介绍;
转载:http://www.cnblogs.com/zhangwei595806165/p/5735959.html
Laravel与Repository Pattern(仓库模式)的更多相关文章
- laravel 5.5 仓库模式 文件之间接口与实现操作
仓库模式 最直接的意思就是: Eloquent数据(数据库)查询 方便快捷,简单明了.自己怎么写的,就怎么去调用,完全ok~ 本质意思: 仓库就像是业务内部的数据对象集合,负责协调业务和数据映射层之 ...
- How To Use The Repository Pattern In Laravel
The Repository Pattern in Laravel is a very useful pattern with a couple of great uses. The first us ...
- Laravel Repository Pattern
Laravel Repository Pattern The Repository Pattern can be very helpful to you in order to keep your ...
- Thinking In Design Pattern——MVP模式演绎
原文<Thinking In Design Pattern——MVP模式演绎>不知为何丢失了,故重新整理了一遍. 目录 What Is MVP Domain Model StubRepos ...
- 学习笔记之ASP.NET MVC & MVVM & The Repository Pattern
ASP.NET MVC | The ASP.NET Site https://www.asp.net/mvc ASP.NET MVC gives you a powerful, patterns-ba ...
- Follow me to learn what is repository pattern
Introduction Creating a generic repository pattern in an mvc application with entity framework is th ...
- Generic repository pattern and Unit of work with Entity framework
原文 Generic repository pattern and Unit of work with Entity framework Repository pattern is an abstra ...
- Using the Repository Pattern with ASP.NET MVC and Entity Framework
原文:http://www.codeguru.com/csharp/.net/net_asp/mvc/using-the-repository-pattern-with-asp.net-mvc-and ...
- Provider Pattern提供者模式和策略模式
http://www.codeproject.com/Articles/18222/Provider-Pattern Introduction Provider pattern is one of t ...
随机推荐
- C# 获取Excel中的合并单元格
C# 获取Excel中的合并单元格 我们在制作表格时,有时经常需要合并及取消合并一些单元格.在取消合并单元格时需要逐个查找及取消,比较麻烦.这里分享一个简单的方法来识别Excel中的合并单元格,识别这 ...
- 基於tiny4412的Linux內核移植--- 中斷和GPIO學習(2)
作者 彭東林 pengdonglin137@163.com 平臺 tiny4412 ADK Linux-4.4.4 u-boot使用的U-Boot 2010.12,是友善自帶的,爲支持設備樹和uIma ...
- 【NLP】揭秘马尔可夫模型神秘面纱系列文章(二)
马尔可夫模型与隐马尔可夫模型 作者:白宁超 2016年7月11日15:31:11 摘要:最早接触马尔可夫模型的定义源于吴军先生<数学之美>一书,起初觉得深奥难懂且无什么用场.直到学习自然语 ...
- 深入理解CSS动画animation
× 目录 [1]定义 [2]关键帧 [3]动画属性 [4]多值 [5]API 前面的话 transition过渡是通过初始和结束两个状态之间的平滑过渡实现简单动画的:而animation则是通过关键帧 ...
- Lua 安全调用 metatable 的简单应用
事情的经过 我们的项目中存在好几个战斗界面,不过界面中的内容略有不同.跟同事出去吃饭的时候,他问我.我们现在的战斗界面.有很多是重复的,但是也有偶尔几个地方不太一样.我在战斗过程中驱动这些界面的时候. ...
- Ionic2系列-将beta升级到RC1
国庆节前Ionic2发布了RC0版本,已经接近正式版了,前不久Angular2和TypeScript2也已经发布了正式版.详情请参考官方博客: http://blog.ionic.io/announc ...
- EChart使用
EChart ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等 ...
- Python 基础之四初识Python数据类型
数字 Int,整型 Float,浮点型 Long,长整型 布尔 字符串 列表 元组 字典 1.数字 INT(整型) 在32位系统上,整数的位数为32位,取值范围为-2**31~2**31-1,即-21 ...
- Android 手机卫士7--黑名单拦截
1,黑名单数据库创建 三个字段(_id 自增长字段 phone 黑名单号码 mode 拦截类型) 创建表的sql语句 create table blacknumber (_id integer pri ...
- Maven创建web项目:SpringMVC+Mybatis 【转】
IDEA14创建Maven管理的SpringMVC+Mybatis,web项目 项目构建步骤 1.File->New->Project 勾选Create from archetype 点击 ...