Tworzenie i konfigurowanie reaktorów w PHP z użyciem pakietu Spatie

Reaktor w PHP, podobnie jak projektor, nasłuchuje nadchodzących zdarzeń. Jednak w przeciwieństwie do projektorów, reaktory nie zostaną wywołane podczas odtwarzania zdarzeń. Reaktory zostaną wywołane tylko wtedy, gdy wystąpi oryginalne zdarzenie.

Tworzenie reaktorów

Rozpocznijmy od stworzenia reaktora. Możesz użyć poniższej komendy Artisan, aby utworzyć reaktor w katalogu app\Reactors:

				
					php artisan make:reactor BigAmountAddedReactor

				
			

Rejestracja reaktorów

Domyślnie pakiet automatycznie znajdzie i zarejestruje wszystkie reaktory znalezione w Twojej aplikacji.

Alternatywnie, możesz również ręcznie zarejestrować je w kluczu reactors pliku konfiguracyjnego event-sourcings.

Mogą również zostać dodane do Projectionist. Można to zrobić w dowolnym miejscu, ale zazwyczaj wykonuje się to w ServiceProviderze.

				
					namespace App\Providers;

use App\Projectors\AccountBalanceProjector;
use Illuminate\Support\ServiceProvider;
use Spatie\EventSourcing\Facades\Projectionist;

class EventSourcingServiceProvider extends ServiceProvider
{
    public function register()
    {
        // dodanie pojedynczego reaktora
        Projectionist::addReactor(BigAmountAddedReactor::class);

        // można również dodać wiele reaktorów naraz
        Projectionist::addReactors([
            AnotherReactor::class,
            YetAnotherReactor::class,
        ]);
    }
}

				
			

Korzystanie z reaktorów

Oto zawartość klasy stworzonej przez komendę Artisan wymienioną w sekcji powyżej:

				
					namespace App\Reactors;

class MyReactor
{
    public function onEventHappened(EventHappened $event)
    {
        // obsługa zdarzenia
    }
}

				
			

Uzyskiwanie UUID zdarzenia

W większości przypadków będziesz chciał mieć dostęp do zdarzenia, które zostało wywołane. Aby uzyskać dostęp do UUID zdarzenia, wystarczy wywołać metodę aggregateRootUuid() na obiekcie zdarzenia.

				
					public function onMoneyAdded(MoneyAdded $event)
{
    $account = Account::findByUuid($event->aggregateRootUuid());
    
    Mail::to($account->user)->send(new MoreMoneyAddedMailable());
}

				
			

Ręczna rejestracja metod obsługi zdarzeń

Właściwość $handlesEvents jest tablicą, która ma klasy zdarzeń jako klucze i nazwy metod jako wartości. Za każdym razem, gdy zostanie wywołane zdarzenie, które pasuje do jednego z kluczy w $handlesEvents, odpowiadająca metoda zostanie wywołana.

Oto przykład, w którym nasłuchujemy zdarzenia MoneyAdded:

				
					namespace App\Reactors;

use App\Events\MoneyAdded;

class BigAmountAddedReactor
{
    /*
     * Tutaj możesz określić, które zdarzenie powinno wywołać jaką metodę.
     */
    protected array $handlesEvents = [
        MoneyAdded::class => 'onMoneyAdded',
    ];

    public function onMoneyAdded(MoneyAdded $event)
    {
        // wykonaj jakieś działanie
    }
}

				
			

Używanie domyślnych nazw metod obsługi zdarzeń

W powyższym przykładzie zdarzenia są mapowane na metody reaktora za pomocą właściwości $handlesEvents.

				
					// w reaktorze

// ...

protected array $handlesEvents = [
    MoneyAdded::class => 'onMoneyAdded',
];

				
			

Możesz to napisać trochę krócej. Po prostu umieść nazwę klasy zdarzenia w tej tablicy. Pakiet będzie wnioskował nazwę metody do wywołania. Założy, że istnieje metoda o nazwie on po której następuje nazwa zdarzenia. Oto przykład:

				
					// w reaktorze

// ...

protected array $handlesEvents = [
    /*
     * Jeśli to zdarzenie zostanie przekazane do reaktora, metoda `onMoneyAdded` zostanie wywołana.
     */ 
    MoneyAdded::class,
];

				
			

Obsługa pojedynczego zdarzenia

Możesz $handleEvent do nazwy klasy zdarzenia. Gdy takie zdarzenie nadejdzie, zostanie wywołana metoda __invoke.

				
					// w reaktorze

// ...

protected $handleEvent =  MoneyAdded::class,

public function __invoke(MoneyAdded $event)
{
    // obsługa zdarzenia
}

				
			

Użycie klasy jako obsługi zdarzenia

Zamiast pozwalania metodzie na reaktorze obsługiwać zdarzenie, można użyć dedykowanej klasy.

				
					// w projektorze

// ...

protected array $handlesEvents = [
    /*
     * Jeśli to zdarzenie zostanie przekazane do projektora, zostanie wywołana klasa `SendMoneyAddedMail`.
     */ 
    MoneyAdded::class => SendMoneyAddedMail::class,
];

				
			

Oto przykładowa implementacja SendMoneyAddedMail:

				
					use App\Events\MoneyAdded;

class SendMoneyAddedMail
{
    public function __invoke(MoneyAdded $event)
    {
        // wykonaj pracę wysyłającą maila tutaj
    }
}

				
			

Dostosowywanie kolejności reaktorów

Możesz dodać właściwość weight do reaktora, aby dostosować kolejność, w jakiej są uruchamiane reaktory. Reaktory z niższą wagą są uruchamiane jako pierwsze. Gdy nie jest podana jawnie waga, uważa się, że waga wynosi 0.

				
					namespace App\Reactors;

class MyReactor
{
    public int $weight = 5;
}

				
			

Należy zauważyć, że podanie wagi na reaktorze kolejkowanym nie gwarantuje kolejności wykonania.

Podsumowanie

Pakiet Spatie Event Sourcing zapewnia wygodne narzędzia do tworzenia i zarządzania reaktorami w aplikacjach PHP. Dzięki prostemu mapowaniu zdarzeń na metody obsługi oraz możliwości dodawania wag reaktorów, możesz łatwo kontrolować logikę biznesową Twojej aplikacji w oparciu o zdarzenia.