Laravel のリポジトリ パターン (Repository) の利点の簡単な分析
Laravel でリポジトリ パターン (Repository) を使用する理由は何ですか?リポジトリモードを利用するメリットについては以下の記事で紹介していますので、ぜひ参考にしてください。
前回の記事では、リポジトリ パターンとは何か、Active Record パターンとの違い、Laravel での実装方法について説明しました。ここで、なぜリポジトリ パターンを使用する必要があるのかを詳しく見ていきたいと思います。 前の記事のコメントで、
リポジトリ パターンが Laravel コミュニティで物議を醸すトピックであることに気付きました。これを使用する理由がないと考えて、組み込みのアクティブ レコード モードを使い続ける人もいます。他の方法を使用してデータ アクセスを論理ドメインから分離することを好む人もいます。私はこれらの意見を尊重し、今後のブログ投稿でこのトピックを取り上げることに注意してください。
この免責事項を踏まえて、リポジトリ パターンを使用する利点を理解しましょう。単一責任の原則
単一責任の原則は、アクティブ レコード モードとリポジトリ モードを区別する主な識別子です。モデル クラスはすでにデータを保持し、ドメイン オブジェクトのメソッドを提供します。 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();
その唯一の目的は、ドメイン オブジェクト自体ではなく、ドメイン オブジェクトのコレクションを識別することです。
キーポイント:
- #ウェアハウス パターンは、すべてのドメイン オブジェクトのコレクションを単一のドメイン オブジェクトから分離することにより、単一責任の原則を具体化します
- 。
Don't Reply Yourself (DRY)一部のプロジェクトでは、プロジェクト全体にデータベース クエリが散布されています。以下は、データベースからリストを取得し、ブレード ビューに表示する例です。
class InvoiceController { public function index(): View { return view('invoices.index', [ 'invoices' => Invoice::where('overdue_since', '>=', Carbon::now()) ->orderBy('overdue_since') ->paginate() ]); } }
このようなクエリがより複雑になり、複数の場所で使用される場合は、それを Repository メソッドに抽出することを検討してください。
リポジトリ パターンは、重複クエリを式メソッドにパッケージ化することで重複クエリを減らすのに役立ちます。クエリを調整する必要がある場合、変更する必要があるのは 1 回だけです。
class InvoiceController { public __construct(private InvoiceRepository $repo) {} public function index(): View { return view('invoices.index', [ 'invoices' => $repo->paginateOverdueInvoices() ]); } }
これで、クエリは 1 回だけ実装され、単独でテストして他の場所で使用できるようになりました。さらに、コントローラーはデータの取得については責任を負わず、HTTP リクエストを処理して応答を返すことのみを担当するため、単一責任原則が再び適用されます。
要点:? リポジトリ パターンは重複クエリの削減に役立ちます
説明
依存関係逆転の原則これは、独自のブログ投稿に値します。リポジトリによって依存関係の逆転が可能になることを説明したかっただけです。 コンポーネントを階層化する場合、通常、上位レベルのコンポーネントは下位レベルのコンポーネントに依存します。たとえば、コントローラーはモデル クラスに依存してデータベースからデータを取得します。
class InvoiceController { public function index(int $companyId): View { return view( 'invoices.index', ['invoices' => Invoice::where('company_id', $companyId)->get()] ); } }
依存関係はトップダウンで緊密に結合されています。
InvoiceController は、特定の Invoice
クラスに依存します。これら 2 つのクラスを個別にテストしたり、ストレージ メカニズムを置き換えたりするなど、これら 2 つのクラスを分離することは困難です。 Repository インターフェイスを導入することで、依存関係の逆転を実現できます: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>interface InvoiceRepository {
public function findByCompanyId($companyId): Collection;
}
class InvoiceController {
public function __construct(private InvoiceRepository $repo) {}
public function index(int $companyId): View {
return view(
&#39;invoices.index&#39;,
[&#39;invoices&#39; => $this->repo->findByCompanyId($companyId)]
);
}
}
class EloquentInvoiceRepository implements InvoiceRepository {
public function findByCompanyId($companyId): Collection {
// 使用 Eloquent 查询构造器实现该方法
}
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
Controller は Repository 実装と同じように、Repository インターフェイスにのみ依存するようになりました。
次のセクションで説明するように、これによりさらなる利点がもたらされます。
- ? 存储库模式作为一种抽象类,支持依赖反转.
抽象类
存储库 提高了可读性 因为复杂的操作被具有表达性名称的高级方法隐藏了.
访问存储库的代码与底层数据访问技术分离. 如有必要,您可以切换实现,甚至可以省略实现,仅提供 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 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

Visual Studio Code (VS Code とも呼ばれる) は、すべての主要なオペレーティング システムで利用できる無料のソース コード エディター (統合開発環境 (IDE)) です。 多くのプログラミング言語の拡張機能の大規模なコレクションを備えた VS Code は、

このチュートリアルでは、PHPを使用してXMLドキュメントを効率的に処理する方法を示しています。 XML(拡張可能なマークアップ言語)は、人間の読みやすさとマシン解析の両方に合わせて設計された多用途のテキストベースのマークアップ言語です。一般的にデータストレージに使用されます

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

文字列は、文字、数字、シンボルを含む一連の文字です。このチュートリアルでは、さまざまな方法を使用してPHPの特定の文字列内の母音の数を計算する方法を学びます。英語の母音は、a、e、i、o、u、そしてそれらは大文字または小文字である可能性があります。 母音とは何ですか? 母音は、特定の発音を表すアルファベットのある文字です。大文字と小文字など、英語には5つの母音があります。 a、e、i、o、u 例1 入力:string = "tutorialspoint" 出力:6 説明する 文字列「TutorialSpoint」の母音は、u、o、i、a、o、iです。合計で6元があります

あなたが経験豊富な PHP 開発者であれば、すでにそこにいて、すでにそれを行っていると感じているかもしれません。あなたは、運用を達成するために、かなりの数のアプリケーションを開発し、数百万行のコードをデバッグし、大量のスクリプトを微調整してきました。

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

PHPの魔法の方法は何ですか? PHPの魔法の方法には次のものが含まれます。1。\ _ \ _コンストラクト、オブジェクトの初期化に使用されます。 2。\ _ \ _リソースのクリーンアップに使用される破壊。 3。\ _ \ _呼び出し、存在しないメソッド呼び出しを処理します。 4。\ _ \ _ get、dynamic属性アクセスを実装します。 5。\ _ \ _セット、動的属性設定を実装します。これらの方法は、特定の状況で自動的に呼び出され、コードの柔軟性と効率を向上させます。
