Publishing From Events
Publishing From an Event
In an event-driven application, a controller dispatches an event so listeners can handle the resulting work:
<?php
namespace App\Http\Controllers;
use App\Events\OrderPaid;
use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class StripeWebhookController extends Controller
{
public function __invoke(Request $request): Response
{
$order = Order::where('payment_intent', $request->input('data.object.id'))
->firstOrFail();
OrderPaid::dispatch($order);
return response()->noContent();
}
}To publish an activity when an event is dispatched, implement the Storyfeed\Contracts\PublishesToFeed interface on the event class. The interface requires a toFeedActivity method, which returns the activity to publish:
<?php
namespace App\Events;
use App\Models\Order;
use Illuminate\Foundation\Events\Dispatchable;
use Storyfeed\Contracts\PublishesToFeed;
use Storyfeed\Facades\Storyfeed;
use Storyfeed\PendingActivity;
class OrderPaid implements PublishesToFeed
{
use Dispatchable;
public function __construct(public Order $order) {}
public function toFeedActivity(): ?PendingActivity
{
return Storyfeed::activity()
->by('Stripe')
->action('pay', $this->order);
}
}Listeners handle tasks such as marking the order paid:
<?php
namespace App\Listeners;
use App\Events\OrderPaid;
class MarkOrderPaid
{
public function handle(OrderPaid $event): void
{
$event->order->update(['paid_at' => now()]);
// The activity is published automatically.
}
}When an event implementing PublishesToFeed is dispatched, Storyfeed calls its toFeedActivity method and publishes the returned activity:
NOTE
Do not call the publish method on the event's activity. Storyfeed publishes it automatically, so another call would record it twice.
Skipping Publication
Return null to skip publishing for this event:
public function toFeedActivity(): ?PendingActivity
{
if ($this->order->isTest()) {
return null;
}
return Storyfeed::activity()
->by('Stripe')
->action('pay', $this->order);
}Use the Storyfeed fake to test publishing. Do not fake the application event, because its listeners must run to call the toFeedActivity method.
Listening for Storyfeed Events
Storyfeed dispatches an event when an activity is published or deleted:
| Event | Payload |
|---|---|
Storyfeed\Events\ActivityPublished | $event->activity: the published activity's values |
Storyfeed\Events\ActivityDeleted | $event->activity: the deleted activity's values |
The $event->activity value is an immutable copy of the activity, not an Eloquent model. Both events are dispatched after the outermost transaction commits. A rollback dispatches neither event.
A listener for these events can implement ShouldQueue. Storyfeed::fake() does not dispatch them, so use Queue::fake() alone when asserting that a listener was queued.
Storyfeed also dispatches BatchClosed when a batch closes. See Listening for Closed Batches.