浅析Laravel中存储库模式(Repository)的优点_第1页
浅析Laravel中存储库模式(Repository)的优点_第2页
浅析Laravel中存储库模式(Repository)的优点_第3页
浅析Laravel中存储库模式(Repository)的优点_第4页
浅析Laravel中存储库模式(Repository)的优点_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第浅析Laravel中存储库模式(Repository)的优点在之前的文章中,我解释了什么是存储库模式,它与ActiveRecord模式有何不同,以及如何在Laravel中实现它。现在我想深入了解一下为什么应该使用存储库模式。

我在上一篇文章的评论中注意到,Repository模式在Laravel社区中是一个有争议的话题。有些人认为没有理由使用它,并坚持使用内置的ActiveRecord模式。其他人则倾向于使用其他方法将数据访问从逻辑域中分离出来。请注意,我尊重这些意见,并将在接下来的博客文章中专门讨论此主题。

有了这个免责声明,让我们来了解一下使用存储库模式的优点。

单一责任原则

单一责任原则是主要鉴别器来区分ActiveRecord模式和存储库模式。模型类已经保存数据并提供域对象的方法。当使用ActiveRecord模式时,数据访问是额外引入的责任。这是我想在以下示例中说明的东西:

*@propertystring$first_name

*@propertyint$company_id

classEmployeeextendsModel{}

$jack=newEmployee();

$jack-first_name=Jack

$jack-company_id=$twitterId;

$jack-save();

虽然域模型和数据访问技术的职责混合,但它直观上看还说得过去。在我们的应用程序中,员工必须以某种方式存储在数据库中,因此为什么不调用对象上的save()。单个对象被转化成单个数据行并存储。

但是,让我们更进一步,看看我们还能对员工做些什么:

$jack-where(first_name,John)-firstOrFAIl()-delete();

$competition=$jack-where(company_id,$facebookId)-get();

现在,它变得不直观,甚至违背了我们的域模型。为什么Jack会突然删除另一个甚至可能在不同公司工作的员工?或者他为什么能把Facebook的员工拉过来?

当然,这个例子是人为设计的,但它仍然显示了ActiveRecord模式如何不允许有意的域模型。员工与所有员工列表之间的界限变得模糊。您始终必须考虑该员工是被用作实际员工还是作为访问其他员工的机制。

仓库模式通过强制执行这个基本分区来解决这个问题。它的唯一用途是标识域对象的合集,而不是域对象的本身。

要点:

通过将所有域对象的集合与单个域对象分离,仓库模式体现了单一责任原则。

不要重复自己(DRY)

一些项目将数据库查询洒遍了整个项目。下面是一个例子,我们从数据库中获取列表,并在Blade视图中显示他们。

classInvoiceController{

publicfunctionindex():View{

returnview(invoices.index,[

invoices=Invoice::where(overdue_since,=,Carbon::now())

-orderBy(overdue_since)

-paginate()

}

当这样的查询遍得更加复杂并且在多个地方使用时,考虑将其提取到Repository方法中。

存储库模式通过将重复查询打包到表达方法中来帮助减少重复查询。如果必须调整查询,只需更改一次即可。

classInvoiceController{

public__construct(privateInvoiceRepository$repo){}

publicfunctionindex():View{

returnview(invoices.index,[

invoices=$repo-paginateOverdueInvoices()

}

现在查询只实现一次,可以单独测试并在其他地方使用。此外,单一责任原则再次发挥作用,因为控制器不负责获取数据,而只负责处理HTTP请求和返回响应。

Takeaway:

存储库模式有助于减少重复查询

解释DependencyInversionPrinciple值得发表自己的博客文章。我只是想说明存储库可以启用依赖项反转。

在对组件进行分层时,通常较高级别的组件依赖于较低级别的组件。例如,控制器将依赖模型类从数据库中获取数据:

classInvoiceController{

publicfunctionindex(int$companyId):View{

returnview(

invoices.index,

[invoices=Invoice::where(company_id,$companyId)-get()]

}

依赖关系是自上而下的,紧密耦合的。InvoiceController取决于具体的Invoice类。很难将这两个类解耦,例如单独测试它们或替换存储机制。通过引入Repository接口,我们可以实现依赖倒置:

interfaceInvoiceRepository{

publicfunctionfindByCompanyId($companyId):Collection;

classInvoiceController{

publicfunction__construct(privateInvoiceRepository$repo){}

publicfunctionindex(int$companyId):View{

returnview(

invoices.index,

[invoices=$this-repo-findByCompanyId($companyId)]

classEloquentInvoiceRepositoryimplementsInvoiceRepository{

publicfunctionfindByCompanyId($companyId):Collection{

//使用Eloquent查询构造器实现该方法

}

Controller现在只依赖于Repository接口,和Repository实现一样.这两个类现在只依赖于一个抽象,从而减少耦合.正如我将在下一节中解释的那样,这会带来更多优势.

Takeaway:

存储库模式作为一种抽象类,支持依赖反转.

存储库提高了可读性因为复杂的操作被具有表达性名称的高级方法隐藏了.

访问存储库的代码与底层数据访问技术分离.如有必要,您可以切换实现,甚至可以省略实现,仅提供Repository接口。这对于旨在与框架无关的库来说非常方便。

OAuth2服务包league/oauth2-server也用到这个抽象类机制。LaravelPassport也通过实现这个库的接口集成league/oauth2-server包。

正如@bdelespierre在评论里回应我之前的一篇博客文章时向我指出的那样,你不仅可以切换存储库实现,还可以将它们组合在一起。大致以他的示例为基础,您可以看到一个存储库如何包装另一个存储库以提供附加功能:

interfaceInvoiceRepository{

publicfunctionfindById(int$id):Invoice;

classInvoiceCacheRepositoryimplementsInvoiceRepository{

publicfunction__construct(

privateInvoiceRepository$repo,

privateint$ttlSeconds

){}

publicfunctionfindById(int$id):Invoice{

returnCache::remember(

invoice.$id,

$this-ttlSeconds,

fn():Invoice=$this-repo-findById($id)

classEloquentInvoiceRepositoryimplementsInvoiceRepository{

publicfunctionfindById(int$id):Invoice{/*从数据库中取出$id*/}

//---用法:

$repo=newInvoiceCacheRepository(

newEloquentInvoiceRepository();

);

要点:

存储库模式抽象了有关数据访问的详细信息。

存储库将客户端与数据访问技术分离。

这允许切换实现,提高可读性并实现可组合性。

存储库模式提供的抽象也有助于测试。

如果你有一个Repository接口,你可以提供一个替代的测试实现。您可以使用数组支持存储库,而不是访问数据库,将所有对象保存在数组中:

classInMemoryInvoiceRepositoryimplementsInvoiceRepositoryInterface{

privatearray$invoices;

//implementthemethodsbyaccessing

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论