Maison  >  Article  >  cadre php  >  Le modèle de référentiel Laravel récemment populaire (Repository)

Le modèle de référentiel Laravel récemment populaire (Repository)

藏色散人
藏色散人avant
2021-11-15 15:38:302666parcourir

La colonne tutorielle suivante de Le modèle de référentiel Laravel récemment populaire (Repository) vous présentera le mode référentiel Le modèle de référentiel Laravel récemment populaire (Repository) (Repository).

Le modèle de référentiel Laravel récemment populaire (Repository)

  • 1. Modèle de référentiel (Référentiel) dans Le modèle de référentiel Laravel récemment populaire (Repository)
  • 2. Pourquoi utiliser le modèle de référentiel (Référentiel) dans Le modèle de référentiel Laravel récemment populaire (Repository) ?

Dans la plupart des applications Web, l'accès à la base de données représente une grande partie de la base de code. Pour éviter d'encombrer notre logique applicative avec des requêtes SQL, nous nous appuyons sur des abstractions, qui cachent les mécanismes d'accès aux données derrière les méthodes PHP.

Il existe plusieurs modes d'accès structuré aux données, "Active Record" et "Repository" sont les deux plus connus. Dans cet article de blog, je les expliquerai spécifiquement dans le contexte du framework Le modèle de référentiel Laravel récemment populaire (Repository). La discussion sur les avantages et les inconvénients de l’utilisation du modèle Repository sera abordée dans un article de blog séparé.

Active Record

Par défaut, Le modèle de référentiel Laravel récemment populaire (Repository) utilise le mode Active Record. Chaque programmeur Le modèle de référentiel Laravel récemment populaire (Repository) l'utilise de manière intuitive car il est implémenté dans la classe de base abstraite Model, dont les modèles héritent généralement. Regardons un exemple :

use Illuminate\Database\Eloquent\Model;

/**
 * @property int    $id
 * @property string $first_name
 * @property string $last_name
 */
class Person extends Model {
}

// --- 使用:

$person = new Person();
$person->first_name = 'Jack';
$person->last_name = 'Smith';
$person->save();

Bien sûr, vous pouvez lire et écrire les propriétés que vous créez sur Person. Mais pour sauvegarder le modèle, vous pouvez aussi Person 上创建的属性。 但是要保存模型,您也可以 直接在模型上调用方法。 不需要另一个对象——模型已经提供了访问相应数据库表的所有方法。

这意味着,域模型将您的自定义属性和方法与同一类中的所有数据访问方法相结合。 第二部分是通过继承 Model 来实现的。

要点:

  • Active Record 结合 域模型与数据访问功能。
  • Le modèle de référentiel Laravel récemment populaire (Repository) 使用 Active Record 模式并通过 Model 类实现它。

Repository

Repository 模式是 Active Record 模式的替代方案。它还提供了处理数据访问的抽象。但更广泛地说,它可以被视为域对象的概念性存储库或集合。

与活动记录模式相反,存储模式将数据库访问与域模型分离。它提供了一个高级接口,你可以在其中创建、读取、更新和删除域模型,而不必考虑实际的底层数据存储。

底层的存储库可以通过构建和执行 SQL 查询访问数据库,通过 REST APIappeler des méthodes directement sur le modèle

. Pas besoin d'un autre objet - le modèle fournit déjà toutes les méthodes pour accéder à la table de base de données correspondante.

Cela signifie que le modèle de domaine combine vos propriétés et méthodes personnalisées avec toutes les méthodes d'accès aux données de la même classe. La deuxième partie est réalisée en héritant du Model.

    Points clés :
  • Active Record
  • combine
  • modèle de domaine et fonctions d'accès aux données.

Le modèle de référentiel Laravel récemment populaire (Repository) utilise le modèle Active Record et l'implémente via la classe Model.

Repository

Le modèle de référentiel est une alternative au modèle Active Record. Il fournit également des abstractions pour gérer l'accès aux données.

Mais plus largement, il peut être considéré comme un référentiel conceptuel ou une collection d'objets de domaine.

Contrairement au modèle d'enregistrement actif, le modèle de stockage sépare l'accès à la base de données du modèle de domaine. Il fournit une interface de haut niveau dans laquelle vous pouvez créer, lire, mettre à jour et supprimer des modèles de domaine sans avoir à vous soucier du magasin de données sous-jacent réel.

Le référentiel sous-jacent peut accéder aux bases de données en créant et en exécutant des requêtes SQL, accéder aux systèmes distants via l'API REST ou simplement gérer les structures de données en mémoire qui contiennent tous les modèles de domaine. Ceci est utile pour les tests. L'élément clé du modèle de référentiel est l'interface de haut niveau qu'il fournit au reste du code.

    Points clés :
  • Le référentiel représente une collection conceptuelle d'objets de domaine.
  • Il est uniquement chargé d'encapsuler l'accès aux données avec des interfaces de haut niveau.
  • Le modèle de référentiel Laravel récemment populaire (Repository) ne fournit pas d'aides spécifiques pour implémenter le modèle Repository
  • Lorsqu'il s'agit d'implémenter le modèle Repository dans Le modèle de référentiel Laravel récemment populaire (Repository), je vois principalement deux variantes.
Variation 1 : Méthode spécifique

Dans la première variante, la méthode du référentiel est ciblée et spécifique. Le nom explique ce que l'appelant obtient et les options de paramétrage de la requête sous-jacente sont limitées.

class InvoiceRepository {

    public function findAllOverdue(Carbon $since, int $limit = 10): Collection {
        return Invoice::where('overdue_since', '>=', $since)
            ->limit($limit)
            ->orderBy('overdue_since')
            ->get();
    }

    public function findInvoicedToCompany(string $companyId): Collection {
        return Invoice::where('company_id', $companyId)
            ->orderByDesc('created_at')
            ->get();
    }
}
L'avantage de cette méthode est l'expressivité de la méthode. Lors de la lecture du code, il est clair à quoi s'attendre des méthodes et comment les appeler. Cela entraîne moins d’erreurs. Les méthodes de référentiel sont faciles à tester car elles ont des paramètres limités. L'un des inconvénients de cette approche est que vous risquez de devoir utiliser un grand nombre de méthodes dans le référentiel. Étant donné que les méthodes ne peuvent pas être facilement réutilisées, des méthodes supplémentaires doivent être ajoutées pour de nouveaux cas d'utilisation.

Points :

🎜🎜🎜Le schéma de stockage peut être implémenté par des classes qui fournissent des méthodes spécifiques🎜🎜Chaque méthode encapsule une requête, exposant uniquement les paramètres nécessaires🎜🎜🎜Avantages :🎜Lisibilité et testabilité🎜🎜🎜 Inconvénients : 🎜 Manque de flexibilité et réutilisabilité moindre 🎜🎜🎜Variation 2 : Méthode générale 🎜🎜Une approche, en revanche, consiste à fournir une méthode générale. Cela a entraîné une réduction des méthodes. 🎜Mais ces méthodes ont une grande surface API🎜, puisque chaque méthode peut être appelée avec différentes combinaisons de paramètres. 🎜🎜🎜Le problème clé est la représentation des paramètres🎜. Cette représentation doit guider les appelants dans la compréhension des signatures de méthode et éviter les entrées non valides. Pour ce faire, vous pouvez introduire une classe spéciale, par exemple en utilisant le modèle Query Object. 🎜

但是我在实践中经常看到的是标量参数和 PHP 数组的混合。调用方可以传递完全无效的输入,仅类型数据并不能说明要传递什么。但是如果使用得当,这种轻量级的方法可以避免更繁琐的抽象。

class InvoiceRepository {

    public function find(array $conditions, string $sortBy = 'id', string $sortOrder = 'asc', int $limit = 10): Collection {
        return Invoice::where($conditions)
            ->orderBy($sortBy, $sortOrder)
            ->limit($limit)
            ->get();
    }
}

// --- 使用:

$repo = new InvoiceRepository();
$repo->find(['overdue_since', '>=', $since], 'overdue_since', 'asc');
$repo->find(['company_id', '=', $companyId], 'created_at', 'asc', 100);

这种方法减轻了第一种方法的问题:你可以得到更少的 Repository 方法,这些方法更灵活,并且可以更频繁地重用。

从消极的方面看,Repository 变得更加难以测试,因为有更多的案例需要覆盖。方法签名更难理解,正因为如此,调用者可能会犯更多错误。此外,还将引入某种查询对象表示形式。无论它是显式的还是隐式的(比如数组),您的 Repository 实现及其调用者都将与它耦合。

要点:

  • 存储库模式可以通过提供通用方法的类实现。
  • 难点在于方法参数的表示。
  • 优点: 更大的灵活性和更高的可复用性。
  • 缺点: 更难测试,可读性差,与参数表示耦合。

当然,这两种方法可以结合起来使用。也许你想要一些特定的方法用于复杂的查询,而一些通用的方法用于简单的 where 查询。

实现

现在,我们来谈谈如何实现方法体。

在上面的例子中,我使用了 Model 类的方法来获得对 Eloquent 查询构造器的访问。所以 Repository 的实现实际上使用了 Active Record 模式作为实现。

你不需要这样做。你可以使用 DB facade 来获得一个查询构建器,同时避免使用 Model 类。或者你可以直接编写 SQL 查询:

class InvoiceRepository {

    public function findAllOverdue(Carbon $since, int $limit = 10): Collection {
        return DB::table('invoices')
            ->where('overdue_since', '>=', $since)
            ->limit($limit)
            ->orderBy('overdue_since')
            ->get();
    }

    public function findInvoicedToCompany(string $companyId): Collection {
        return DB::select('SELECT * FROM invoices
                           WHERE company_id = ?
                           ORDER BY created_at
                           LIMIT 100', [$companyId]);
    }
}

存储模式的优点是,实现可以是任何东西,只要它满足接口。你还可以管理内存中的对象或者包(和缓存)一个 API。

但是最常见的是,底层数据存储是一个 SQL 数据库。要访问它,你可以根据每个方法选择最佳实现。对于性能关键的或者复杂的查询,你可能希望直接使用 SQL 语句。更简单的查询可以使用 Eloquent 查询生成器。

当你没有使用 模型 类来实现你的 Repository ,你可能会考虑在模型中不继承它。但是这个方法违反了很多内置的 Le modèle de référentiel Laravel récemment populaire (Repository) 魔术方法,在我看来并不是一个好的方法。

要点:

  • 存储库模式很灵活,允许使用各种实现技术。
  • 在 Le modèle de référentiel Laravel récemment populaire (Repository) 中,当访问数据库时,Eloquent 查询构建器是一个实用的选择。

接口

你的另一个选择是,是否要引入一个接口。上面的例子可以用一个接口和一个或多个实现来分隔:

// --- 接口:

public interface InvoiceRepositoryInterface {

    public function findAllOverdue(Carbon $since, int $limit = 10): Collection;

    public function findInvoicedToCompany(string $companyId): Collection;
}

// --- 具体的类,实现了该接口

class InvoiceRepository implements InvoiceRepositoryInterface {

    public function findAllOverdue(Carbon $since, int $limit = 10): Collection {
        // 实现
    }

    public function findInvoicedToCompany(string $companyId): Collection {
        // 实现
    }
}

添加接口是一种额外的间接方法,并不一定是好的。如果您的应用程序是 Repository 的唯一用户,并且您不希望它有多个实现,那么我不认为引入接口有什么意义。对于测试,Repository 可以用 PHPUnit 模拟,只要它不被标记为 final

如果你知道你将有多个实现,你应该使用一个接口。如果你正在编写一个将在多个项目中使用的 包。或者你想要测试一个特殊的 Repository 实现,那么可能会发生不同的实现。

为了从 Le modèle de référentiel Laravel récemment populaire (Repository) 的依赖注入中获益,你必须将具体的实现绑定到接口上。这必须在服务提供者的注册方法中完成。

use Illuminate\Support\ServiceProvider;

class RepositoryServiceProvider extends ServiceProvider {

    public function register(): void {
        $this->app->bind(InvoiceRepositoryInterface::class, InvoiceRepository::class);
    }
}

要点:

  • 一个接口可以进一步 解耦 从代码的其余部分获取代码库。
  •  当您期望有多个具体类实现它时,使用 Repository 接口。
  • 在 Le modèle de référentiel Laravel récemment populaire (Repository) 中,将具体类绑定到服务提供者中的接口。

原文地址:https://dev.to/davidrjenni/repository-pattern-in-laravel-1pph

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer