検索
ホームページPHPフレームワークLaravelLaravel のリポジトリ パターン (Repository) の利点の簡単な分析

Laravel でリポジトリ パターン (Repository) を使用する理由は何ですか?リポジトリモードを利用するメリットについては以下の記事で紹介していますので、ぜひ参考にしてください。

Laravel のリポジトリ パターン (Repository) の利点の簡単な分析

  • 1. Laravel のリポジトリ パターン
  • 2. Laravel でリポジトリを使用する理由パターン(リポジトリ)?
前回の記事では、リポジトリ パターンとは何か、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();

これでは、直感的ではなくなり、ドメイン モデルに違反することさえあります。なぜジャックは、別の会社で働いているかもしれない別の従業員を突然削除したのでしょうか?あるいは、なぜ彼は Facebook の従業員を呼び寄せることができたのでしょうか?

もちろん、この例は不自然ですが、アクティブ レコード パターンが意図的なドメイン モデルをどのように許可していないかを示しています。従業員と全従業員のリストとの境界線があいまいになります。従業員が実際の従業員として使用されているのか、他の従業員にアクセスするためのメカニズムとして使用されているのかを常に考慮する必要があります。

ウェアハウス モードは、この基本的なパーティショニングを強制することでこの問題を解決します。

その唯一の目的は、ドメイン オブジェクト自体ではなく、ドメイン オブジェクトのコレクションを識別することです。

キーポイント:

    #ウェアハウス パターンは、すべてのドメイン オブジェクトのコレクションを単一のドメイン オブジェクトから分離することにより、単一責任の原則を具体化します

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 インターフェイスを導入することで、依存関係の逆転を実現できます: <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( &amp;#39;invoices.index&amp;#39;, [&amp;#39;invoices&amp;#39; =&gt; $this-&gt;repo-&gt;findByCompanyId($companyId)] ); } } class EloquentInvoiceRepository implements InvoiceRepository { public function findByCompanyId($companyId): Collection { // 使用 Eloquent 查询构造器实现该方法 } }</pre>Controller は Repository 実装と同じように、Repository インターフェイスにのみ依存するようになりました。

これら 2 つのクラスは 1 つの抽象化にのみ依存するようになりました

次のセクションで説明するように、これによりさらなる利点がもたらされます。

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

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

访问存储库的代码与底层数据访问技术分离. 如有必要,您可以切换实现,甚至可以省略实现,仅提供 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(&#39;findInvoicedToCompany&#39;)
    ->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 サイトの他の関連記事を参照してください。

声明
この記事はlearnkuで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
Laravelの汎用性:単純なサイトから複雑なシステムまでLaravelの汎用性:単純なサイトから複雑なシステムまでApr 13, 2025 am 12:13 AM

Laravel Developmentプロジェクトは、さまざまなサイズと複雑さのニーズに合う柔軟性とパワーのために選択されました。 Laravelは、ルーティングシステム、Eloquentorm、Artisan Command Lineおよびその他の機能を提供し、簡単なブログから複雑なエンタープライズレベルのシステムへの開発をサポートしています。

Laravel(PHP)vs。Python:開発環境とエコシステムLaravel(PHP)vs。Python:開発環境とエコシステムApr 12, 2025 am 12:10 AM

開発環境とエコシステムにおけるLaravelとPythonの比較は次のとおりです。1。Laravelの開発環境は簡単で、PHPと作曲家のみが必要です。 Laravelforgeなどの豊富な範囲の拡張パッケージを提供しますが、拡張パッケージのメンテナンスはタイムリーではない場合があります。 2。Pythonの開発環境もシンプルで、PythonとPIPのみが必要です。エコシステムは巨大で複数のフィールドをカバーしていますが、バージョンと依存関係の管理は複雑な場合があります。

LaravelとThe BackEnd:Webアプリケーションロジックの電源LaravelとThe BackEnd:Webアプリケーションロジックの電源Apr 11, 2025 am 11:29 AM

Laravelはバックエンドロジックでどのように役割を果たしますか?ルーティングシステム、Eloquentorm、認証と承認、イベントとリスナー、パフォーマンスの最適化を通じてバックエンド開発を簡素化および強化します。 1.ルーティングシステムにより、URL構造の定義とリクエスト処理ロジックが可能になります。 2.Eloquentormは、データベースの相互作用を簡素化します。 3.認証および承認システムは、ユーザー管理に便利です。 4.イベントとリスナーは、ゆるく結合したコード構造を実装します。 5.パフォーマンスの最適化により、キャッシュとキューイングを通じてアプリケーションの効率が向上します。

Laravelがそんなに人気があるのはなぜですか?Laravelがそんなに人気があるのはなぜですか?Apr 02, 2025 pm 02:16 PM

Laravelの人気には、単純化された開発プロセスが含まれ、快適な開発環境を提供し、豊富な機能が提供されます。 1)Rubyonrailsの設計哲学を吸収し、PHPの柔軟性を組み合わせています。 2)Eloquentorm、Bladeテンプレートエンジンなどのツールを提供して、開発効率を向上させます。 3)そのMVCアーキテクチャと依存関係噴射メカニズムにより、コードがよりモジュール化され、テスト可能になります。 4)キャッシュシステムやベストプラクティスなどの強力なデバッグツールとパフォーマンス最適化方法を提供します。

どちらが良いのか、DjangoとLaravel?どちらが良いのか、DjangoとLaravel?Mar 28, 2025 am 10:41 AM

DjangoとLaravelはどちらもフルスタックのフレームワークです。 DjangoはPython開発者や複雑なビジネスロジックに適していますが、LaravelはPHP開発者とエレガントな構文に適しています。 1.DjangoはPythonに基づいており、迅速な発展と高い並行性に適した「バッテリーコンプリート」哲学に従います。 2. LaravelはPHPに基づいており、開発者エクスペリエンスを強調しており、小規模から中規模のプロジェクトに適しています。

どちらがより良いPHPですか、それともLaravelですか?どちらがより良いPHPですか、それともLaravelですか?Mar 27, 2025 pm 05:31 PM

LaravelはPHPベースのフレームワークであるため、PHPとLaravelは直接匹敵するものではありません。 1.PHPは、シンプルで直接的であるため、小規模プロジェクトや迅速なプロトタイピングに適しています。 2。LARAVELは、豊富な機能とツールを提供するため、大規模なプロジェクトや効率的な開発に適していますが、急な学習曲線があり、純粋なPHPほど良くない場合があります。

Laravelはフロントエンドですか、それともバックエンドですか?Laravelはフロントエンドですか、それともバックエンドですか?Mar 27, 2025 pm 05:31 PM

laravelisabackendframeworkbuiltonphp、designforwebapplicationdevelopment.itfocusonserver-sidelogic、databasemanagement、およびapplicationStructure、およびbueithedendtechnologiesvue.jsorreactforfull-stackdevelymentと統合されていること。

Laravelでカスタムブレードディレクティブを作成および使用するにはどうすればよいですか?Laravelでカスタムブレードディレクティブを作成および使用するにはどうすればよいですか?Mar 17, 2025 pm 02:50 PM

この記事では、Laravelでカスタムブレードディレクティブの作成と使用を行い、テンプレートを強化します。ディレクティブの定義、テンプレートでそれらを使用し、大規模なプロジェクトでそれらを管理することをカバーし、改善されたコードの再利用性やRなどの利点を強調しています

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

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

ホットツール

MantisBT

MantisBT

Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境