Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
浅析Laravel中存储库模式(Repository)的优点_创想鸟

浅析Laravel中存储库模式(Repository)的优点

为什么要在 laravel 中使用存储库模式(repository)?下面本篇文章给大家介绍一下使用存储库模式的优点,希望对大家有所帮助!

浅析Laravel中存储库模式(Repository)的优点

1. Laravel中的存储库模式2. 为什么要在 Laravel 中使用存储库模式(Repository)?

在之前的文章中,我解释了什么是存储库模式,它与Active Record模式有何不同,以及如何在Laravel中实现它。现在我想深入了解一下为什么应该使用存储库模式。

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

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

单一责任原则

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

/** * @property string $first_name * @property int    $company_id */class Employee extends Model {}$jack = new Employee();$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 的员工拉过来?

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

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

要点:

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

不要重复自己 (DRY)

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

class InvoiceController {    public function index(): View {        return view('invoices.index', [            'invoices' => Invoice::where('overdue_since', '>=', Carbon::now())                ->orderBy('overdue_since')                ->paginate()        ]);    }}

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

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

class InvoiceController {    public __construct(private InvoiceRepository $repo) {}    public function index(): View {        return view('invoices.index', [            'invoices' => $repo->paginateOverdueInvoices()        ]);    }}

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

Takeaway:

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

依赖反转

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

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

class InvoiceController {    public function index(int $companyId): View {        return view(            'invoices.index',            ['invoices' => Invoice::where('company_id', $companyId)->get()]        );    }}

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

存了个图 存了个图

视频图片解析/字幕/剪辑,视频高清保存/图片源图提取

存了个图 17 查看详情 存了个图

interface InvoiceRepository {    public function findByCompanyId($companyId): Collection;}class InvoiceController {    public function __construct(private InvoiceRepository $repo) {}    public function index(int $companyId): View {        return view(            'invoices.index',            ['invoices' => $this->repo->findByCompanyId($companyId)]        );    }}class EloquentInvoiceRepository implements InvoiceRepository {    public function findByCompanyId($companyId): Collection {        // 使用 Eloquent 查询构造器实现该方法    }}

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

Takeaway:

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

抽象类

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

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

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

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

interface InvoiceRepository {    public function findById(int $id): Invoice;}class InvoiceCacheRepository implements InvoiceRepository {    public function __construct(        private InvoiceRepository $repo,        private int $ttlSeconds    ) {}    public function findById(int $id): Invoice {        return Cache::remember(            "invoice.$id",            $this->ttlSeconds,            fn(): Invoice => $this->repo->findById($id)        );    }}class EloquentInvoiceRepository implements InvoiceRepository {    public function findById(int $id): Invoice { /* 从数据库中取出 $id */ }}// --- 用法:$repo = new InvoiceCacheRepository(    new EloquentInvoiceRepository(););

要点:

? 存储库模式抽象了有关数据访问的详细信息。? 存储库将客户端与数据访问技术分离。? 这允许切换实现,提高可读性并实现可组合性。

可测试性

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

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

class InMemoryInvoiceRepository implements InvoiceRepositoryInterface {    private array $invoices;    // implement the methods by accessing $this->invoices...}// --- Test Case:$repo = new InMemoryInvoiceRepository();$service = new InvoiceService($repo);

通过这种方法,您将获得一个现实的实现,它速度很快并且在内存中运行。 但是您必须为测试提供正确的 Repository 实现,这 ** 本身可能需要大量工作**。 在我看来,这在两种情况下是合理的:

您正在开发一个(与框架无关的)库,它本身不提供存储库实现。

测试用例复杂,Repository 的状态很重要。

另一种方法是“模仿”,要使用这种技术,你不需要适当的接口。你可以模仿任何 non-final 类。
使用 PHPUnit API ,您可以明确规定如何调用存储库以及应该返回什么。

$companyId = 42;/** @var InvoiceRepository&MockObject */$repo = $this->createMock(InvoiceRepository::class);$repo->expects($this->once())    ->method('findInvoicedToCompany')    ->with($companyId)    ->willReturn(collect([ /* invoices to return in the test case */ ]));$service = new InvoiceService($repo);$result = $service->calculateAvgInvoiceAmount($companyId);$this->assertEquals(1337.42, $result);

有了 mock,测试用例就是一个适当的单元测试。上面示例中测试的唯一代码是服务。没有数据库访问,这使得测试用例的设置和运行非常快速

另外:

? 仓库模式允许进行适当的单元测试,这些单元测试运行快并且是隔离的

原文地址:https://dev.to/davidrjenni/why-use-the-repository-pattern-in-laravel-2j1m

译文地址:https://learnku.com/laravel/t/62521

【相关推荐:laravel视频教程】

以上就是浅析Laravel中存储库模式(Repository)的优点的详细内容,更多请关注php中文网其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/339988.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
优酷会员怎么自动跳过片头片尾_优酷会员片头片尾跳过功能使用
上一篇 2025年11月5日 17:50:09
如何使用Composer解决Symfony项目中的密码强度验证问题
下一篇 2025年11月5日 17:50:21

相关推荐

  • Laravel 8 登录后重定向至仪表盘的策略与实践

    本教程详细阐述了在 Laravel 8 中实现用户登录后重定向到仪表盘的多种策略。我们将探讨如何通过配置 LoginController 的 $redirectTo 属性、利用 RouteServiceProvider 定义常量以及在自定义登录方法中进行精确控制来管理重定向流程。文章还涵盖了相关中间…

    2026年9月22日
    000
  • Grok官方网站直达页_Grok官网官方网页版入口

    Grok官网官方网页版入口为https://grok.com,用户可通过该网站访问网页端服务,支持跨设备同步;同时可下载移动应用或在X平台内使用Grok功能。未订阅用户可体验基础功能,Premium及Premium+需通过X平台订阅,SuperGrok则仅在官网提供,具备更强数据处理能力。账户升级后…

    2026年9月22日
    600
  • PHP如何利用缓存优化实时输出_PHP实时输出与缓存结合优化

    PHP实时输出需结合输出缓冲控制与flush()强制推送,同时考虑服务器和浏览器缓存影响;2. 长时间任务应使用APCu或Redis缓存频繁数据,避免重复计算;3. 动态页面可采用分块输出与片段缓存策略,静态内容从缓存读取,动态部分边生成边输出;4. 更优方案是通过异步任务与Redis存储进度,前端…

    2026年9月22日
    000
  • VS Code中Dockerized PHP项目:解决PHP版本冲突的教程

    本教程旨在解决在VS Code中开发Dockerized PHP项目时,VS Code默认识别宿主机PHP版本而非容器内PHP版本的问题。核心解决方案是利用VS Code的Remote – Containers扩展,实现直接在Docker容器内部进行代码开发,从而确保VS Code及其所…

    2026年9月22日
    200
  • PHP each() 函数的替代方案:自定义实现与常见错误修正

    本文探讨了PHP中已废弃的each()函数的替代方案。针对常见的自定义实现,如myEach(),文章详细指出了其在返回数组结构中常犯的错误,并提供了正确的代码示例,以确保替代函数能够模拟each()的预期行为,帮助开发者编写更健壮、兼容未来的PHP代码。 理解 each() 函数及其废弃背景 在PH…

    2026年9月22日
    000
  • 解决PHP应用中本地文件更新后网页视图不刷新的缓存问题

    本文探讨了PHP应用中,本地JSON或图片文件更新后,网页视图无法实时刷新的常见问题。核心原因在于浏览器缓存机制。文章将提供多种解决方案,包括强制刷新、隐身模式诊断、以及通过URL参数、服务器配置(.htaccess)和文件版本控制来有效管理缓存,确保用户始终获取最新数据。 理解问题:本地文件更新与…

    2026年9月22日
    200
  • laravel中的契约(Contracts)和门面(Facades)有什么关系_Laravel契约与门面关系解析

    Laravel中的契约定义服务接口,门面提供静态代理,二者协同实现松耦合与易用性:契约通过依赖注入保障可测试性与类型安全,门面通过静态调用简化语法,实际底层对象通常实现对应契约,如Cache门面代理实现IlluminateContractsCacheRepository接口的实例,两者可依场景灵活选…

    2026年9月22日
    100
  • Laravel 8 登录后重定向到仪表盘:完整教程

    本教程详细阐述了在 Laravel 8 中实现用户登录后重定向到仪表盘的多种方法。我们将探讨 Laravel 默认的重定向机制、如何正确配置仪表盘路由及其中间件,并提供通过自定义 LoginController 实现精确重定向的示例代码。通过本文,您将全面掌握 Laravel 认证后的重定向流程,并…

    2026年9月22日
    500
  • 一键PHP环境怎么解决网页空白问题_空白页故障诊断

    答案是开启错误提示并检查文件路径与代码逻辑。先启用PHP错误显示,确认配置正确;再核对网站根目录和入口文件是否存在;接着排查代码致命错误及输出缓冲问题,确保无BOM头且session前无输出。 遇到一键PHP环境安装后出现网页空白或空白页问题,通常不是环境完全失效,而是某些关键环节出了错。这类问题在…

    2026年9月21日
    100
  • MySQL字段注释快速补全方法_Sublime脚本自动生成标准文档结构

    MySQL字段注释快速补全方法_Sublime脚本自动生成标准文档结构MySQL字段注释快速补全方法_Sublime脚本自动生成标准文档结构MySQL字段注释快速补全方法_Sublime脚本自动生成标准文档结构MySQL字段注释快速补全方法_Sublime脚本自动生成标准文档结构

    要快速补全mysql字段注释,可通过sublime text编写python脚本实现自动化;1. 脚本获取表名,可手动输入或从当前sql文件解析;2. 通过subprocess调用mysql命令行获取show full columns信息;3. 解析输出内容,提取字段名和现有注释;4. 生成alte…

    2026年9月21日 用户投稿
    200
  • PHP三元运算符HTML输出_PHP三元运算符HTML内容输出

    PHP三元运算符用于在HTML中简洁输出条件内容,基本语法为“条件 ? 值1 : 值2”;2. 常用于动态显示文本、属性或样式,如根据$active输出“启用”或“禁用”;3. 可嵌入HTML标签设置class、disabled等属性,示例中根据登录状态显示不同按钮。 PHP三元运算符用于在HTML…

    2026年9月21日
    200
  • 巧文书AI官网首页官方入口 巧文书AI在线文档编辑官网链接直达

    巧文书AI官网首页官方入口是https://qiaowenshu.cn,该平台提供AI驱动的文档生成、智能解析、语义扩展、在线编辑与保存等功能,支持多场景文案创作和跨设备同步,具备一键润色、风格推荐及模板管理等智能化写作辅助体验。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用…

    2026年9月21日
    100
  • 微信读书网页官方登录入口_微信读书在线阅读官方网站链接

    微信读书在线阅读官方网站链接是https://weread.qq.com/,提供海量图书资源、多设备同步、社交化阅读、听书功能及免费专区与会员体系。 微信读书网页官方登录入口在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来微信读书在线阅读官方网站链接,感兴趣的网友一起随小编来瞧瞧吧! ht…

    2026年9月21日
    200
  • PHP中基于参考数组过滤多维数组并保持结构一致性

    本教程详细阐述了如何在PHP中,根据一个参考数组来过滤多维数组的特定子数组,并同步移除其他子数组中对应索引的元素,最终实现数组的结构化筛选和重新索引。文章通过实际案例和代码演示,指导读者高效地处理复杂数组的匹配与清理任务。 在php开发中,我们经常会遇到需要对复杂数据结构进行筛选和整理的场景。例如,…

    2026年9月21日
    100
  • laravel集合有where方法吗

    有。Laravel集合中的where方法是一个非常有用的方法,用于在集合中筛选元素,根据指定的条件返回匹配的元素。使用where方法,可以根据不同的条件来过滤集合中的元素,where方法接受一个闭包作为参数,闭包中可以定义筛选的条件,闭包的每个元素都会传递给闭包。无论是对关联数组还是对对象集合,wh…

    2026年9月21日
    100
  • laravel如何判断请求类型

    laravel判断请求类型的方法:1、使用Request对象的方法,在Laravel中,每个请求都会通过Request对象进行处理。Request对象提供了一些有用的方法来判断请求类型;2、使用路由方法,在Laravel中,路由文件定义了应用程序的请求路由,可以使用路由方法来判断请求类型;3、使用中…

    2026年9月21日
    100
  • Laravel 8 登录后重定向到仪表盘的完整教程

    本教程详细介绍了在 Laravel 8 中实现用户登录后重定向到仪表盘的多种方法。我们将探讨如何利用 Laravel 内置的 $redirectTo 属性,以及如何通过重写 LoginController 中的 login 方法来实现自定义重定向逻辑。此外,教程还将重点讲解正确的路由配置和中间件使用…

    2026年9月21日
    100
  • laravel怎么监控错误

    laravel监控错误的方法:1、错误日志记录,Laravel内置了一个非常强大的日志系统,可以通过查看这些日志文件来了解应用程序中发生的错误;2、异常处理,Laravel提供了一个Exception类,可以用来捕获和处理异常;3、自定义错误页面,创建不同的视图文件,用于处理特定类型错误,当发生相应…

    2026年9月21日
    100
  • PHP一键环境如何配置URL重写_URL Rewrite规则设置

    开启Apache的mod_rewrite模块并配置AllowOverride All,再在.htaccess中添加重写规则,即可实现URL重写,使URL更简洁利于SEO。 在使用PHP一键环境(如XAMPP、WAMP、phpStudy等)时,开启URL重写(URL Rewrite)功能可以让网站的U…

    2026年9月21日
    200
  • 解决WordPress wp-settings.php中致命错误的实用指南

    当WordPress网站遭遇wp-settings.php中Call to undefined function的致命错误时,通常意味着核心文件已损坏。本教程将指导您通过下载全新WordPress副本并替换站点中wp-admin和wp-includes目录来有效解决此问题,确保网站恢复正常运行,并提…

    2026年9月21日
    100

发表回复

登录后才能评论
关注微信