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 ...
随机推荐
- 日常css技巧小结(2)-- inline-block带来的迷惑
一.问题描述 在平时布局中,inline-block使用的频率比很高,主要是因为可以让行标签设置宽高.我在布局过程中,发现了两个“问题”, 1行标签.display:inline-block之后的行标 ...
- 一个技术汪的开源梦 —— 基于 .Net Core 的公共组件之目录结构
一个技术汪的开源梦 —— 目录 这篇文章是开源公共组件的开篇那就先说说项目的 Github 目录结构和 .Net Core 的项目结构. 1. GitHub 目录结构和相关文件 - src 源码项目目 ...
- C++异常处理:try,catch,throw,finally的用法
写在前面 所谓异常处理,即让一个程序运行时遇到自己无法处理的错误时抛出一个异常,希望调用者可以发现处理问题. 异常处理的基本思想是简化程序的错误代码,为程序键壮性提供一个标准检测机制. 也许我们已经使 ...
- 产品前端重构(TypeScript、MVC框架设计)
最近两周完成了对公司某一产品的前端重构,本文记录重构的主要思路及相关的设计内容. 公司期望把某一管理类信息系统从项目代码中抽取.重构为一个可复用的产品.该系统的前端是基于 ExtJs 5 进行构造的, ...
- 【趣味分享】C#实现回味童年的24点算法游戏
一.24点游戏玩法规则效果展示 1.初始化界面 2.开始游戏界面 3.游戏超时界面 4.查看答案界面 5.答对界面 6.答错界面 7.计算表达式的验证界面 8.一副牌算完开始新一副牌界面 到这里24点 ...
- Github Pages和Hexo创建静态博客网站
Github Pages和Hexo创建静态博客网站 安装Node.js 本人是window环境,所以下载window版. 下载地址:https://nodejs.org/en/download/ 下载 ...
- SQL SERVER 竖表变成横表
现有数据如下: Sql: select a.MODELID, max( case a.PNAME when'计划开始' then a.PVALUE end) as RStart, max( case ...
- DNS原理及其解析过程 精彩剖析
本文章转自下面:http://369369.blog.51cto.com/319630/812889 DNS原理及其解析过程 精彩剖析 网络通讯大部分是基于TCP/IP的,而TCP/IP是基于IP地址 ...
- 手机端访问web调用数字键盘。
转自 http://www.webkfa.com/one4/w1937.html 最近在做手机页面时,遇到数字输入的键盘的问题,之前的做法只是一刀切的使用 type="tel", ...
- wamp集成环境开启rewrite伪静态支持
wamp集成环境在安装完后,默认是没有开启伪静态的,所以有时把项目部署进去时如果源码里包含.htaccess文件的话,可能会出现500错误,这一般是因为不支持伪静态造成的,解决这个问题的办法就是开启伪 ...