Explication détaillée des étapes de mise en œuvre des événements du modèle Laravel

php中世界最好的语言
Libérer: 2023-03-26 14:16:01
original
2037 Les gens l'ont consulté

Cette fois, je vais vous apporter une explication détaillée des étapes pour implémenter les événements du modèle Laravel. Quelles sont les précautions pour implémenter les événements du modèle Laravel, jetons un coup d'œil.

Préface

Le modèle ORM de Laravel déclenchera une série d'événements dans certaines circonstances. Les événements actuellement pris en charge sont les suivants : création, création,. mettre à jour, mettre à jour, enregistrer, sauvegarder, supprimer, supprimer, restaurer, restaurer, alors comment cette fonction est-elle implémentée au niveau inférieur ?

Pas grand chose à dire ci-dessous, jetons un œil à l'introduction détaillée.

1. Comment utiliser les événements de modèle

Voyons d'abord comment utiliser les événements de modèle. Il existe deux méthodes écrites dans le. En fait, il existe au total trois façons de définir un événement modèle. Ici, nous prenons l'exemple de l'événement enregistré. Les autres événements sont les mêmes.

Attribut 1.events

Code direct :

class User extends Authenticatable {
 use Notifiable;
 protected $events = [
  'saved' => UserSaved::class,
 ];
}
Copier après la connexion

C'est difficile à comprendre, et le document ne l'explique pas en détail. Je le pensais au début. Après le déclenchement de l'enregistrement, la méthode handle dans UserSaved sera appelée, mais ce n'est pas réellement le cas. Ce tableau n'est qu'un mappage d'événements. Il définit que l'événement UserSaved sera déclenché lorsque le modèle est enregistré. Nous devons également définir l'événement et son écouteur :

namespace App\Events;
use App\User;
class UserSaved {
 public $user;
 public function construct(User $user){
  $this->user = $user;
 }
}
Copier après la connexion
namespace App\Listeners;
class UserSavedListener {
 public function handle(UserSaved $userSaved){
  dd($userSaved);
 }
}
Copier après la connexion

Ensuite, vous avez besoin. pour enregistrer l'événement et l'écouteur dans EventServiceProvider :

class EventServiceProvider extends ServiceProvider
{
 /**
  * The event listener mappings for the application.
  *
  * @var array
  */
 protected $listen = [
  'App\Events\UserSaved' => [
   'App\Listeners\UserSavedListener',
  ]
 ];
 /**
  * Register any events for your application.
  *
  * @return void
  */
 public function boot()
 {
  parent::boot();
 }
}
Copier après la connexion

De cette façon, lorsque le nœud enregistré est enregistré, l'événement UserSaved sera déclenché et la méthode handle de son écouteur UserSavedListener sera appelée.

2. Observateur

Il s'agit d'une méthode de définition d'événement modèle recommandée par le document, et elle est plus facile à comprendre :

use App\User;
class UserObserver
{
 /**
  * 监听用户创建事件.
  *
  * @param User $user
  * @return void
  */
 public function created(User $user)
 {
  //
 }
 /**
  * 监听用户创建/更新事件.
  *
  * @param User $user
  * @return void
  */
 public function saved(User $user)
 {
  //
 }
}
Copier après la connexion
Enregistrez ensuite l'observateur dans la méthode de démarrage d'un fournisseur de services :

namespace App\Providers;
use App\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
 /**
  * Bootstrap any application services.
  *
  * @return void
  */
 public function boot()
 {
  User::observe(UserObserver::class);
 }
 /**
  * Register the service provider.
  *
  * @return void
  */
 public function register()
 {
  //
 }
}
Copier après la connexion
De cette façon, lorsque l'événement de modèle est déclenché, la méthode correspondante de UserObserver sera appelée. En fait, lorsque nous utilisons des observateurs, en plus de certains de ceux fournis avec le système, nous pouvons également définir certains de nos propres événements :

class User extends Authenticatable {
 use Notifiable;
 protected $observables = [
  'customing', 'customed'
 ];
}
Copier après la connexion
puis définir des méthodes du même nom dans l'observateur. :

class UserObserver
{
 /**
  * 监听用户创建/更新事件.
  *
  * @param User $user
  * @return void
  */
 public function saved(User $user)
 {
  //
 }
 public function customing(User $user){
 }
  public function customed(User $user){
 }
}
Copier après la connexion
Comme il s'agit d'un événement défini par nous-mêmes, il doit être déclenché manuellement lorsqu'il est déclenché. Il suffit d'appeler une méthode fireModelEvent dans le modèle où il doit être déclenché. Cependant, comme cette méthode est protégée, elle ne peut être utilisée que dans la méthode modèle définie par vous-même. Bien sûr, si elle est appelée par réflexion, elle peut être déclenchée directement sur l'objet $user. Je n'ai pas essayé cela, mais vous. pouvez le tester vous-même.

class User extends Authenticatable {
 use Notifiable;
 protected $observables = [
  'customing', 'awesoming'
 ];
 
 public function custom(){
  if ($this->fireModelEvent('customing') === false) {
   return false;
  }
  
  //TODO
   if ($this->fireModelEvent('customed') === false) {
   return false;
  }
 }
}
Copier après la connexion

3. Définition de la méthode statique

On peut également définir un événement via la méthode statique correspondante sur le modèle, définie dans la méthode de démarrage d'EventServiceProvider :

class EventServiceProvider extends ServiceProvider{
 /**
  * Register any events for your application.
  *
  * @return void
  */
 public function boot()
 {
  parent::boot();
  User::saved(function(User$user) {
  });
  User::saved('UserSavedListener@saved');
 }
}
Copier après la connexion
Lorsqu'il est défini via une méthode statique, il peut être transmis directement dans une fermeture, ou il peut être défini comme une méthode d'une certaine classe. Lorsque l'événement est déclenché, le paramètre transmis est le modèle. exemple.

2. Principe de mise en œuvre des événements modèles

Tous les codes pour les événements modèles de Laravel sont sous le trait IlluminateDatabaseEloquentConcernsHasEvents. Comment enregistrer ces événements, où $dispatcher est une instance du répartiteur d'événements IlluminateContractsEventsDispatcher, injectée dans la méthode de démarrage d'IlluminateDatabaseDatabaseServiceProvider.

protected static function registerModelEvent($event, $callback){
  if (isset(static::$dispatcher)) {
   $name = static::class;
   static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback);
  }
 }
Copier après la connexion
C'est ici que les événements Laravel sont enregistrés, avec eloquent.saved:AppUser comme nom d'événement et $callback comme gestionnaire. Cette méthode d'enregistrement des événements enregistrera uniquement ceux définis comme observateurs et méthodes statiques. Si vous le définissez comme attribut $events du modèle, Laravel ne l'enregistrera pas et le déclenchera de manière synchrone lorsque l'événement sera déclenché, qui sera analysé ensuite.

Ensuite, un tas de méthodes sont définies dans HasEvents comme suit. Ce sont les principes de définition des écouteurs d'événements via les méthodes statiques ci-dessus. Vous pouvez les comprendre en un coup d'œil sans autre explication.

public static function saving($callback){
 static::registerModelEvent('saving', $callback);
}
public static function saved($callback){
 static::registerModelEvent('saved', $callback);
}
Copier après la connexion
Alors comment définir les auditeurs d'événements sous la forme d'observateurs ? Regardez le code source :

 public static function observe($class){
  $instance = new static;
  $className = is_string($class) ? $class : get_class($class);
  foreach ($instance->getObservableEvents() as $event) {
   if (method_exists($class, $event)) {
    static::registerModelEvent($event, $className.'@'.$event);
   }
  }
 }
 public function getObservableEvents()
 {
  return array_merge(
   [
    'creating', 'created', 'updating', 'updated',
    'deleting', 'deleted', 'saving', 'saved',
    'restoring', 'restored',
   ],
   $this->observables
  );
 }
Copier après la connexion
Obtenez d'abord le nom de classe de l'observateur, puis déterminez s'il existe une méthode correspondant au nom de l'événement. Si elle existe, appelez registerModelEvent pour enregistrer le nom de l'événement. inclut ici également celui que nous avons défini dans le tableau observables.

Une fois les événements et les auditeurs définis, il est temps de les déclencher. Comme mentionné précédemment, il existe une méthode fireModelEvent. Jetons un coup d'œil au code source :

.

 protected function fireModelEvent($event, $halt = true)
 {
  if (! isset(static::$dispatcher)) {
   return true;
  }
  $method = $halt ? 'until' : 'fire';
  $result = $this->filterModelEventResults(
   $this->fireCustomModelEvent($event, $method)
  );
  if ($result === false) {
   return false;
  }
  return ! empty($result) ? $result : static::$dispatcher->{$method}(
   "eloquent.{$event}: ".static::class, $this
  );
 }
Copier après la connexion

其中比较关键的一个方法是fireCustomModelEvent,它接受一个事件名以及触发方式。顺带一提,filterModelEventResults这个方法的作用就是把监听器的返回值为null的过滤掉。

看看fireCustomModelEvent的源码:

 protected function fireCustomModelEvent($event, $method)
 {
  if (! isset($this->events[$event])) {
   return;
  }
  $result = static::$dispatcher->$method(new $this->events[$event]($this));
  if (! is_null($result)) {
   return $result;
  }
 }
Copier après la connexion

这个就是用来触发我们通过$events定义的事件了,假如我们这么定义:

class User extends Model{
 protected $events = [
  'saved' => UserSaved::class
 ]
}
Copier après la connexion

那这里的触发就是:

 $result = static::$dispatcher->fire(new UserSaved($this));
Copier après la connexion

顺带一提,Laravel中触发事件的方法有两个,一个是常用的fire,还有一个是util,这两个的差别就是fire会把监听器的返回值返回,而util永远返回null

然后接下来就是会去触发通过观察者和静态方法定义的监听器了,这一段代码:

  if ($result === false) {
   return false;
  }
  return ! empty($result) ? $result : static::$dispatcher->{$method}(
   "eloquent.{$event}: ".static::class, $this
  );
Copier après la connexion

这里会先判断$events定义的监听器是否返回false以及返回值是否为空,如果为false则直接结束事件,如果返回不为false而且为空的话,会再去触发通过观察者和静态方法定义的监听器,并且把监听器的返回值返回。
完。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

phpStudy2018安装与配置步骤详解

ThinkPHP实现微信支付(jsapi支付)步骤详解

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!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal