2016-06-03 5 views
9

데이터베이스를 외부 서비스와 동기화하려고합니다.Laravel 다중 모델 이벤트

웹 응용 프로그램의 몇 곳에서 알골시아 검색을 사용하고 있습니다.

두 개의 모델로 색인이 생성되었지만 데이터베이스에 변경 사항이 발생하는 경우 (즉, 여러 모델 이벤트가 발생하는 경우) 색인을 다시 생성해야합니다.

내 첫 번째 방법은 AppServiceProvider

public function boot() 
{ 
    $events = ['created', 'updated', 'deleted', 'restored']; 

    // reindex handlers for models relevant to Algolia search 
    foreach ($events as $evt) { 
     Order::registerModelEvent($evt, function() { 
      Order::reindex(); 
     }); 
     Product::registerModelEvent($evt, function() { 
      Product::reindex(); 
      Product::setSettings(); 
     }); 
    } 
} 

부팅 메서드 내에서 행동 모든 것을했다 이것을 docs에 exampled 표준 모델 기능을 사용하여 여러 조건문을 피하기 위해 내 접근 방식입니다.

그러나 Laravel Event Listeners를 사용하는 것이 더 좋은 방법이라고 가정합니다.

namespace App\Listeners; 

class OrderEventListener 
{ 
    // handlers 

    public function subscribe($events) 
    { 
     $events->listen(
      // model events 
     ); 
    } 
} 

나는 의 모델 이벤트를 활용하는 방법을 확실 해요하지만

방법을들을 수 있습니다.

답변

7

이 상황에 맞는 이벤트와 처리기를 추가하는 것이 좋습니다. 당신은 당신의 자신의 ProductCreatedEvent 객체를 생성해야합니다

class Product extends Model 
{ 
    protected static function boot() 
    { 
     parent::boot(); 

     self::created(function($product) { 
      event(new ProductCreatedEvent($product)); 
     }); 
    } 
} 

: 당신의 ProductOrder 클래스에서

당신은 모델의 boot 방법을 대체 할 수 있습니다. 이제 EventServiceProvider에서 리스너 배열에 추가하려고합니다. 당신이 설정 한 후에

protected $listeners = [ 
    'App\Events\ProductCreatedEvent' => [ 
     'App\Listeners\UpdateAlgoliaProductIndex', 
    ] 
]; 

실제로 php artisan event:generate을 실행할 수 있으며, 이것은 당신을위한 이벤트 객체 및 청취자를 작성합니다. 생성 된 제품을 순수하게 가져 와서 청취자 UpdateAlgoliaProductIndex으로 전송하면 이벤트 객체를 건너 뛸 것입니다.

지금 리스너에 당신이 뭔가를해야합니다 다음

class UpdateAlgoliaProductIndex 
{ 
    public function handle($event) 
    { 
     Product::reindex(); 
     Product::setSettings(); 
    } 
} 

나는이 방법은 당신이 당신이 요청을 차단하지 않는 것을 의미하는 ShouldQueue 인터페이스를 사용하여 수신기를 대기 할 수 있습니다 제안 이유를 Algolia로 앱을 다시 색인화하여 사용자에게 더 나은 환경을 제공 할 수 있습니다.

이벤트 개체 및 수신기에 대한 자세한 내용은 here을 참조하십시오.

대체 옵션은 model observer입니다.

+0

나는 이런 종류의 통지를했습니다. 제품이 업데이트되고 'ProductCreatedEvent'가 시작됩니다. 내가보기에는 부트 메소드에서'self :: updated()'로만 트리거 할 필요가 있기 때문에 괜찮습니다. 그러나 모델 이벤트가 발생할 때마다 여기에서 다시 색인을 생성하는 것과 같은 작업을 수행해야하며 이후 이벤트 리스너, 핸들러 등에서 모든 모델 이벤트를 나열 할 필요가없는 솔루션을 찾고있었습니다. 더 자세히 살펴보면 일자리를 만들고 부츠를 파견하는 것이 더 낫지 않습니까? 그럼 여전히 ShouldQueue 구현할 수 있지만 항상 화재 것입니다. –

+1

모든 모델 이벤트를 원한다면'created'보다는'saved'를 보시면 아마 더 많은 행운을 빕니다. ShouldQueue는 추가되는 Job 객체가 정의 될 필요가 없게한다. 즉각적으로 실행하고 싶지 않다면 제품 오브젝트에'requires_search_indexing' 필드를 추가하는 것이 좋습니다. 그런 다음 업데이트를 그룹화하기 위해 정기적으로 스윕 작업을 할 수 있습니다. –

+0

좋은 지적입니다. 나는 당신이 여전히 모든 이벤트 리스너를 사용하는 것을 주장하고있는 중도를 원한다면 받아들입니다. Laravel 5.2는 모델 관측자를 문서에서 제외 시켰기 때문에 더 이상 접근법을 추천하지 않는지 의심 스럽습니다. –

0

일부 파고 나는 Laravel 이벤트 subscribers을 만났습니다.이 이벤트는 내가 찾고있는 것과 유사하여 자체 응답으로 제출했습니다.

이 코드는 모든 이벤트에 대한 리스너를 갖는 것보다 간결한 코드를 생성한다고 생각합니다.

namespace App\Listeners; 

use App\Events\OrderCreatedEvent; 
use App\Events\OrderUpdatedEvent; 
use Illuminate\Queue\InteractsWithQueue; 
use Illuminate\Contracts\Queue\ShouldQueue; 

class OrderEventListener 
{ 
    /** 
    * Handle order created events. 
    * 
    * @param OrderCreatedEvent $event 
    */ 
    public function onOrderCreation(OrderCreatedEvent $event) 
    { 
     // do something 
    } 

    /** 
    * Handle order updated events. 
    * 
    * @param OrderUpdatedEvent $event 
    */ 
    public function onOrderUpdate(OrderUpdatedEvent $event) 
    { 
     // do something 
    } 

    /** 
    * Register the listeners for the subscriber. 
    * 
    * @param $events 
    */ 
    public function subscribe($events) 
    { 
     $events->listen(
      'App\Events\OrderCreatedEvent', 
      'App\Listeners\OrderEv[email protected]' 
     ); 

     $events->listen(
      'App\Events\OrderUpdatedEvent', 
      'App\Listeners\[email protected]' 
     ); 
    } 
} 

나는 marcus를 유지할 것이다.ramsden 대답은 표기된 바와 같지만 이것은 아마도이 질문을 겪고있는 사람들과 매우 관련이 있습니다.