>  기사  >  백엔드 개발  >  Laravel 모델 이벤트 구현 단계에 대한 자세한 설명

Laravel 모델 이벤트 구현 단계에 대한 자세한 설명

php中世界最好的语言
php中世界最好的语言원래의
2018-05-18 11:13:222034검색

이번에는 Laravel 모델 이벤트 구현 단계에 대해 자세히 설명하겠습니다. Laravel 모델 이벤트 구현 시 주의사항은 무엇인가요?

머리말

Laravel의 ORM 모델은 특정 상황에서 일련의 이벤트를 트리거합니다. 현재 지원되는 이벤트는 생성, 생성, 업데이트, 저장, 저장, 삭제, 삭제, 복원, 복원입니다. 이 기능은 최하위 수준에서 구현됩니까?

아래에서는 할 말이 많지 않으니, 자세한 소개를 살펴보겠습니다.

1. 모델 이벤트 사용 방법

먼저 모델 이벤트 사용 방법을 살펴보겠습니다. 문서에는 실제로 모델 이벤트를 정의하는 방법이 총 3가지가 있습니다. 여기서는 저장된 이벤트를 예로 들어보겠습니다. 다른 모든 이벤트는 동일합니다.

1.events 속성

코드로 바로 이동:

class User extends Authenticatable {
 use Notifiable;
 protected $events = [
  'saved' => UserSaved::class,
 ];
}

이건 이해하기 어렵고 문서에는 자세히 설명되어 있지 않습니다. 처음에는 저장이 트리거된 후 처리 방법이 UserSaved가 호출되지만 실제로는 호출되지 않습니다. 이 배열은 단지 이벤트 매핑입니다. 이는 모델이 저장될 때 UserSaved 이벤트가 트리거되도록 정의합니다. 또한 이벤트와 해당 리스너를 정의해야 합니다.

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

그런 다음 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();
 }
}

이런 방식으로 저장된 노드가 저장되면 UserSaved 이벤트가 트리거되고 해당 리스너 UserSavedListener의 핸들 메서드가 호출됩니다.

2. Observer

이는 문서에서 권장하는 모델 이벤트 정의 방법으로 이해하기 쉽습니다. 먼저 관찰자를 정의합니다.

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)
 {
  //
 }
}

그런 다음 서비스 공급자의 부팅 방법에 관찰자를 등록합니다.

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()
 {
  //
 }
}

이렇게 모델 이벤트가 발생하면 해당 UserObserver 메소드가 호출됩니다. 실제로 관찰자를 사용할 때 시스템과 함께 제공되는 일부 이벤트 외에도 자체 이벤트 중 일부를 정의할 수도 있습니다.

class User extends Authenticatable {
 use Notifiable;
 protected $observables = [
  'customing', 'customed'
 ];
}

그런 다음 관찰자에서 동일한 이름의 메서드를 정의합니다.

class UserObserver
{
 /**
  * 监听用户创建/更新事件.
  *
  * @param User $user
  * @return void
  */
 public function saved(User $user)
 {
  //
 }
 public function customing(User $user){
 }
  public function customed(User $user){
 }
}

자체적으로 정의된 이벤트이므로 수동으로 트리거해야 합니다. 트리거해야 하는 모델에서 fireModelEvent 메소드를 호출하기만 하면 됩니다. 하지만 이 메소드는 보호되어 있기 때문에 직접 정의한 모델 메소드에서만 사용할 수 있으며, 물론 리플렉션을 통해 호출할 경우 $user 객체에서 직접 트리거될 수도 있지만 시도해 보지는 않았습니다. 직접 테스트해볼 수 있습니다.

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;
  }
 }
}

3. 정적 메서드 정의

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');
 }
}

정적 메서드를 통해 정의하면 직접 전달할 수 있습니다. 이벤트가 트리거될 때 전달되는 매개변수는 모델 인스턴스입니다.

2. 모델 이벤트 구현 원칙

Laravel의 모든 모델 이벤트 코드는 IlluminateDatabaseEloquentConcernsHasEvents 특성 아래에 있습니다. $dispatcher가 이벤트 스케줄러에 삽입되는 방식을 살펴보겠습니다. IlluminateDatabaseDatabaseServiceProvider의 부팅 방법.

protected static function registerModelEvent($event, $callback){
  if (isset(static::$dispatcher)) {
   $name = static::class;
   static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback);
  }
 }

여기는 Laravel 이벤트가 등록된 곳입니다. 이벤트 이름은 eloquent.saved:AppUser이고 프로세서는 $callback입니다. 이 이벤트 등록 방법은 관찰자 및 정적 메서드로 정의된 이벤트만 등록합니다. 모델의 $events 속성으로 정의하면 Laravel은 이를 등록하지 않고 이벤트가 트리거될 때 동기적으로 트리거하며 다음에 분석됩니다.

그럼 HasEvents에는 다음과 같이 여러 메소드가 정의되어 있습니다. 위의 정적 메소드를 통해 이벤트 리스너를 정의하는 원리는 따로 설명하지 않아도 한눈에 알 수 있습니다.

public static function saving($callback){
 static::registerModelEvent('saving', $callback);
}
public static function saved($callback){
 static::registerModelEvent('saved', $callback);
}

그럼 이벤트 리스너를 관찰자 형태로 정의하는 방법은 무엇일까요? 소스 코드를 살펴보세요.

 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
  );
 }

먼저 관찰자의 클래스 이름을 가져온 다음, 이벤트 이름에 해당하는 메서드가 있는지 확인합니다. 존재하는 경우 RegisterModelEvent를 호출하여 등록합니다. 관찰 가능 배열에 정의되어 있습니다.

이벤트와 리스너를 정의한 후에는 이를 트리거할 차례입니다. 앞서 언급한 것처럼 fireModelEvent 메소드가 있습니다.

 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
  );
 }

其中比较关键的一个方法是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;
  }
 }

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

class User extends Model{
 protected $events = [
  'saved' => UserSaved::class
 ]
}

那这里的触发就是:

 $result = static::$dispatcher->fire(new UserSaved($this));

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

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

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

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

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

推荐阅读:

phpStudy2018安装与配置步骤详解

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

위 내용은 Laravel 모델 이벤트 구현 단계에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.