Maison >cadre php >Laravel >Parlons de la façon d'utiliser les événements de modèle dans Laravel

Parlons de la façon d'utiliser les événements de modèle dans Laravel

青灯夜游
青灯夜游avant
2022-12-22 21:42:011671parcourir

Parlons de la façon d'utiliser les événements de modèle dans Laravel

Lorsque vous travaillez avec des modèles Eloquent, il est courant de profiter des événements répartis tout au long du cycle de vie du modèle. Il existe différentes manières de procéder, et dans ce didacticiel, je vais les aborder et expliquer les avantages et les inconvénients de chacune. [Recommandation associée : Tutoriel vidéo laravel]

J'utiliserai le même exemple pour chaque méthode afin que vous puissiez comparer directement. Cet exemple attribue la propriété UUID du modèle à l'UUID lors de la création du modèle lui-même.

Notre première approche utilise la méthode bootstrap statique du modèle pour enregistrer le comportement. Cela nous permet de travailler directement sur le modèle et de le créer lors de la création du modèle.

declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

class Office extends Model
{
    public static function boot(): void
    {
        static::creating(fn (Model $model) =>
            $model->uuid = Str::uuid(),
        );
    }
}

Cette approche est idéale pour les petites réactions directes aux événements du modèle, comme l'ajout d'UUID, car elle est très facile à comprendre et vous pouvez voir exactement ce qui se passe sur le modèle. Le plus gros problème de cette approche est la duplication de code. Si vous avez plusieurs modèles auxquels des UUID doivent être attribués, vous ferez la même chose à plusieurs reprises.

Cela nous amène bien à la deuxième approche, utilisant une fonctionnalité. Dans Laravel, si vous créez une méthode sur un trait qui commence par boot et se termine par le nom du trait, vos modèles peuvent hériter du trait et les démarrer automatiquement. Voici un exemple : boot 开头并以 trait 名称结尾的方法,你的模型可以继承 trait 并自动启动它们。这是一个例子:

declare(strict_types=1);

namespace App\Models\Concerns;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

trait HasUuid
{
    public static function bootHasUuid(): void
    {
        static::creating(fn (Model $model) =>
            $model->uuid = Str::uuid(),
        );
    }
}

使用特征允许你将此行为添加到需要它且易于实现的每个模型中。我最大的缺点是,当多个特征想要利用同一个模型事件时,堆叠这些行为可能会导致问题。他们开始争夺优先权,很快就会变得一团糟。

这将我们引向下一个选项,模型观察者。模型观察者是一种基于类的方法来响应模型事件,其中方法对应于被触发的特定事件。

declare(strict_types=1);

namespace App\Observers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

class OfficeObserver
{
    public function creating(Model $model): void
    {
        $model->uuid = Str::uuid();
    }
}

这个类需要在某个地方注册,在服务提供者或模型本身(这是我推荐的地方)。在模型中注册这个观察者可以在模型级别上看到改变雄辩行为的副作用。将其隐藏在服务提供商中的问题在于,除非每个人都知道它的存在,否则很难知道。这种方法的最大缺点是它的可见性。在我看来,正确使用这种方法非常棒。

解决此问题的另一种方法是利用 Eloquent 模型本身的$dispatchesEvents 属性。这是每个 Eloquent 模型上的一个属性,它允许你列出要侦听的事件以及为这些事件调用的类。

declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

class Office extends Model
{
    protected $dispatchesEvents = [
        'creating' => SetModelUuid::class,
    ];
}

SetModelUuid

declare(strict_types=1);

namespace App\Models\Events;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

class SetModelUuid
{
    public function __construct(Model $model)
    {
        $model->uuid = Str::uuid();
    }
}

Utiliser un trait vous permet d'ajouter ce comportement à chaque modèle qui en a besoin et est facile à mettre en œuvre. Mon plus gros inconvénient est que l'empilement de ces comportements peut poser des problèmes lorsque plusieurs fonctionnalités souhaitent tirer parti du même événement de modèle. Ils commencent à se battre pour la priorité et cela devient vite un désastre.

Cela nous amène à l’option suivante, les observateurs modèles. Un observateur de modèle est un moyen basé sur une classe de répondre aux événements du modèle, où la méthode correspond à l'événement spécifique qui a été déclenché.

declare(strict_types=1);

namespace App\Models\Pipelines;

use App\Models\Office

class OfficeCreatingPipeline
{
    public function __construct(Office $model)
    {
        app(Pipeline::class)
            ->send($model)
            ->through([
                ApplyUuidProperty::class,
                TapCreatedBy::class,
            ]);
    }
}

Ce cours doit être inscrit quelque part, soit auprès du prestataire, soit auprès du modèle lui-même (c'est là que je le recommande). L'enregistrement de cet observateur dans le modèle vous permet de voir les effets secondaires d'un changement de comportement éloquent au niveau du modèle. Le problème de le cacher au fournisseur de services est qu'il est difficile de le savoir à moins que tout le monde sache qu'il existe. Le plus gros inconvénient de cette approche est sa visibilité. À mon avis, cette méthode est excellente lorsqu’elle est utilisée correctement.

Une autre façon de résoudre ce problème est de profiter de l'attribut $dispatchesEvents du modèle Eloquent lui-même. Il s'agit d'une propriété sur chaque modèle Eloquent qui vous permet de lister les événements à écouter et les classes à appeler pour ces événements.

rrreee

SetModelUuid sera instancié pendant le cycle de vie du modèle Eloquent, ce qui est votre opportunité d'ajouter des comportements et des propriétés au modèle.

rrreee

Cette approche est l'une des plus claires et des plus faciles à comprendre car le modèle a beaucoup de visibilité et vous pouvez facilement partager cette classe entre les modèles. La plus grande question à laquelle vous serez confronté est de savoir si vous devez déclencher plusieurs actions sur les événements du modèle.

Quoi qu’il en soit, honnêtement, il n’y a pas de bonne façon de procéder. Vous pouvez choisir l'une des méthodes ci-dessus et elles fonctionneront toutes, mais vous devez choisir la méthode qui fonctionne pour vous et votre cas d'utilisation spécifique. J'aimerais voir plus d'options pour cette fonctionnalité spécifique.

Par exemple, si vous devez ajouter plusieurs propriétés à un modèle sur des événements de modèle, les observateurs sont un bon choix. Cependant, est-ce la meilleure option ? Et si nous utilisions l'attribut dispatch events pour exécuter un pipeline personnalisé pour ce modèle ?

rrreee
Comme vous pouvez le voir, nous pouvons commencer à utiliser des pipelines pour ajouter plusieurs comportements pour la modélisation d'événements. Maintenant, cela n'a pas été testé, donc je ne sais pas à 100 % si c'est possible - mais en tant que concept, cela pourrait ouvrir une manière composable de réagir aux événements du modèle.

Comment gérez-vous les événements modèles dans les projets Laravel ? Dites-le-nous sur Twitter !

🎜Adresse originale : https://laravel-news.com/working-with-laravel-model-events🎜🎜Adresse de traduction : https://learnku.com/laravel/t/71183🎜🎜🎜Plus de programmation liée Pour connaissances, veuillez visiter : 🎜Vidéos de programmation🎜 ! ! 🎜

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