laravel5 repository实例教程

本文将介绍Repository的实作,基于的github项目是:l5-repository,源码是做好的教科书,代码面前所有设计意图都无所遁形。

我们首先来明确下需要解决的问题是什么,为什么会出现l5-repository这个项目。

我想你肯定遇到过这个问题:刚开始我们的Model只有几百行,但是呢,随着项目功能的不断复杂,model需要实现的功能也越来越多,当我们有一天突然回过头去看的时候,发现Model已经上千行了,我们自己也想不起来里面都有哪些功能了。

那model为什么会越来越胖呢?我们来看下model中都可能会有哪些功能。

  • php写的业务逻辑
  • 依据显示需求,我们做的数据格式转换,字段的选择性返回
  • 各种条件的查询
  • 对于创建参数、查询参数的验证
  • …..

根据分类,我们可以归纳为下面几类

  1. presenter,显示需求
  2. repository,存取需求
  3. validator,参数验证需求
  4. services,业务逻辑

于是我们就有了下面的架构图:

有了这个图以后,我们再来看l5-repository这个项目的实现,就会容易理解很多。

下面我会从3个方面来讲解l5-repository的实现:repository,presenter,validator。我们先来看repository的实现。

repository原理

开始时,我也免不了一般的套路,先来个repository的定义

A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes.

其核心有两点

  • repository类似于集合,负责对象的存取,隐藏了具体的data mapping的实现
  • repository能根据client构建的查询条件,返回特定的数据

我们先来看第一点,对象存取,说到底就是CRUD操作,于是就有了repository的接口定义RepositoryInterface,具体的接口有:

对于CRUD来说,其最难的是C操作,因为会有各种各样的查询方式,提供的查询接口有:


1

2

3

4

5


public function find($id, $columns = [‘*‘]);

public function findByField($field, $value, $columns = [‘*‘]);

public function findWhere(array $where, $columns = [‘*‘]);

public function findWhereIn($field, array $values, $columns = [‘*‘]);

public function findWhereNotIn($field, array $values, $columns = [‘*‘]);

然后默认的实现是Prettus\Repository\Eloquent\BaseRepository,基本上就是对Eloquent\Builder的一个封装。

但是一些更复杂的查询怎么满足呢?我们难道需要每次有新的查询都去新增findCondition接口吗?显然我们不能这么做,这个时候Criteria就隆重登场了,先看个接口:


1

2

3

4

5

6

7

8

9

10

11

12


interface CriteriaInterface

{

/**

* Apply criteria in query repository

*

* @param $model

* @param RepositoryInterface $repository

*

* @return mixed

*/

public function apply($model, RepositoryInterface $repository);

}

所有的Criteria都需要实现apply方法,看一个可能是实现:


1

2

3

4

5

6

7


class LengthOverTwoHours implements CriteriaInterface {

public function apply($model, Repository $repository)

{

$query = $model->where(‘length‘, ‘>‘, 120);

return $query;

}

}

通过定义LengthOverTwoHours来对Model新增查询,这样子我们每次有新的查询条件,只要新建Criteria即可,满足了开放封闭原则。

接着我们来使用下l5-repository。首先通过命令php artisan make:entity Book来生成文件,然后在[email protected]中新增


1

$this->app->register( RepositoryServiceProvider::class);

接着产生一个Controller


1

php artisan make:controller -r BookController

在里面我们可以使用注入进Repository


1

2

3

4


public function __construct( BookRepository $bookRepository )

{

$this->bookRepository = $bookRepository;

}

然后一些具体的操作可以去看https://github.com/andersao/l5-repository,写的非常详细。

最后介绍下怎么产生criteria,通过下面的命令


1

php artisan make:criteria My

然后添加下面代码


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16


class MyCriteria implements CriteriaInterface

{

/**

* Apply criteria in query repository

*

* @param Builder $model

* @param RepositoryInterface $repository

*

* @return mixed

*/

public function apply($model, RepositoryInterface $repository)

{

$model = $model->where(‘user_id‘,‘=‘, \Auth::user()->id );

return $model;

}

}

就能够使用了,然后在controller中,我们通过下面的方式查询


1

2

3

4

5

6


public function index()

{

$this->repository->pushCriteria(new MyCriteria());

$books = $this->repository->all();

...

}

Presenters优化

接着我们讲Presenters部分。

我们再强调下Presenter解决的问题:把日期、金额、名称之类的呈现(presentation)逻辑抽离出来。在l5-repository这个功能其实不是很满意,我们希望的是1 Presenter中介绍的那种样子,原先样子是:


1

2

3

4

5

6

7

8

9

10

11

12


class Article extends Eloquent

{

public function getDate(){/*...*/}

public function getTaiwaneseDateTime(){/*...*/}

public function getWesternDateTime(){/*...*/}

public function getTaiwaneseDate(){/*...*/}

public function getWesternDate(){/*...*/}

}

抽离出来后是:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18


class Article extends Eloquent

{

public function present()

{

return new ArticlePresenter($this);

}

}

class ArticlePresenter extends Presenter {

public function getTaiwaneseDateTime(){/*...*/}

public function getWesternDateTime(){/*...*/}

public function getTaiwaneseDate(){/*...*/}

public function getWesternDate(){/*...*/}

}

下面是一些实现方案

https://github.com/laracasts/Presenter

https://github.com/robclancy/presenter

https://github.com/laravel-auto-presenter/laravel-auto-presenter

参数验证

最后我们介绍validator

validator的逻辑从model中抽离出来,单独放入一个类中,


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17


use \Prettus\Validator\Contracts\ValidatorInterface;

use \Prettus\Validator\LaravelValidator;

class PostValidator extends LaravelValidator {

protected $rules = [

ValidatorInterface::RULE_CREATE => [

‘title‘ => ‘required‘,

‘text‘ => ‘min:3‘,

‘author‘=> ‘required‘

],

ValidatorInterface::RULE_UPDATE => [

‘title‘ => ‘required‘

]

];

}

能够制定create和update操作的时候不同的验证规则。

总结

以上就是repository的全部,文章开头由实际项目中model越来越胖引出如何给model瘦身,接着对model中的功能进行了划分,给出了合理的项目组织方式,接着通过从repository,presenter,validator分析了具体的一些优化方式。

最后本文只是简单的对l5-repository进行了介绍,更详细的功能,更多的实现细节,你都可以clone项目下来,自己好好去看,相信会学到很多。

参考

胖胖Model減重的五個方法

Using Repository Pattern in Laravel 5

胖胖 MODEL 的減重方法:PRESENTER

Laravel 的中大型專案架構

时间: 2024-10-07 19:03:49

laravel5 repository实例教程的相关文章

React 入门实例教程

React 入门实例教程 作者: 阮一峰 日期: 2015年3月31日 现在最热门的前端框架,毫无疑问是 React . 上周,基于 React 的 React Native 发布,结果一天之内,就获得了 5000 颗星,受瞩目程度可见一斑. React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站.做出来以后,发现这套东西很好用,就在2013年5月开源了. 由于 React 的

室外设计 3D室外效果图教程 Sketchup园林景观教程 室外漫游动画实例教程 景观设计手绘教程

热门推荐电脑办公计算机基础知识教程 Excel2010基础教程 Word2010基础教程 PPT2010基础教程 五笔打字视频教程 Excel函数应用教程 Excel VBA基础教程 WPS2013表格教程 更多>平面设计PhotoshopCS5教程 CorelDRAW X5视频教程 Photoshop商业修图教程 Illustrator CS6视频教程 更多>室内设计3Dsmax2012教程 效果图实例提高教程 室内设计实战教程 欧式效果图制作实例教程 AutoCAD2014室内设计 Aut

室内设计 3Dsmax2012教程 效果图实例提高教程 室内设计实战教程 欧式效果图制作实例教程

热门推荐电脑办公计算机基础知识教程 Excel2010基础教程 Word2010基础教程 PPT2010基础教程 五笔打字视频教程 Excel函数应用教程 Excel VBA基础教程 WPS2013表格教程 更多>平面设计PhotoshopCS5教程 CorelDRAW X5视频教程 Photoshop商业修图教程 Illustrator CS6视频教程 更多>室内设计3Dsmax2012教程 效果图实例提高教程 室内设计实战教程 欧式效果图制作实例教程 AutoCAD2014室内设计 Aut

php页面get方法实现ajax,入门实例教程

ajax,入门实例教程 本例针对php页面,做了一个小的demo加深对ajax的理解 1.文档结构: 共有ajax.php 和action.php 2个页面. 2.源码如下: /*ajax.php页面*/<!DOCTYPE html> <html lang="en"> <head> <title> ajax</title> <script type="text/javascript"> func

Omnet++ 4.0 入门实例教程

http://blog.sina.com.cn/s/blog_8a2bb17d01018npf.html 在网上找到的一个讲解omnet++的实例, 是4.0下面实现的. 我在4.2上试了试,可以用.照着做就能完成,有些小地方不同而已 Omnet++ 4.0 入门实例教程根据http://omnest.com/webdemo/ide 上的实例,自己动手做了做.新版本的4.0 跟它视频上的版本有些差别,配图说明一下我的操作过程,供大家一起学习.现在开始.首先,开发环境选择simulation 的视

网页设计Dreamweaver网页制作 商业网站建设案例课程 ASP.NET基础实例教程 淘宝开店教程

热门推荐电脑办公计算机基础知识教程 Excel2010基础教程 Word2010基础教程 PPT2010基础教程 五笔打字视频教程 Excel函数应用教程 Excel VBA基础教程 WPS2013表格教程 更多>平面设计PhotoshopCS5教程 CorelDRAW X5视频教程 Photoshop商业修图教程 Illustrator CS6视频教程 更多>室内设计3Dsmax2012教程 效果图实例提高教程 室内设计实战教程 欧式效果图制作实例教程 AutoCAD2014室内设计 Aut

Yii2.0论坛实例教程

Yii2.0现在已经出来Beta了,Yii2.0总的来说和Yii1.x还是相差挺大的.现在的教程大部分都还是1.x的,所以这论坛就作为Yii2.0的一个入门实例吧.我也会尽量把Yii2.0的各个新特性以及开发中的技巧一一列出来.如果哪位有兴趣可以一起交流一起来完成.功能列表:http://www.yiifans.com/forum.php?mod=viewthread&tid=68Git地址:https://github.com/yiifans/yiiforum另外,一般情况下会在每天早上提交一

Python logging模块实例教程

position:static(静态定位) 当position属性定义为static时,可以将元素定义为静态位置,所谓静态位置就是各个元素在HTML文档流中应有的位置 podisition定位问题.所以当没有定义position属性时,并不说明该元素没有自己的位置,它会遵循默认显示为静态位置,在静态定位状态下无法通过坐标值(top,left,right,bottom)来改变它的位置. position:absolute(绝对定位) 当position属性定义为absolute时,元素会脱离文档流

Python getopt模块处理命令行选项实例教程

分享下Python getopt模块处理命令行选项的一些例子. 在python编程中,getopt模块与shell中的getopt参数模块一样灵活而实用. getopt模块用于抽出命令行选项和参数,也就是sys.argv 命令行选项使得程序的参数更加灵活.支持短选项模式和长选项模式例如 python scriptname.py -f 'hello' --directory-prefix=/home -t --format 'a' 'b' import getopt, sys shortargs