Pre-1.0. Not intended for public use yet. The API is subject to undocumented change, and these pages may already be wrong about it.

Skip to content

Publishing From Events ​

Publishing From an Event ​

In an event-driven application, a controller dispatches an event so listeners can handle the resulting work:

app/Http/Controllers/StripeWebhookController.php
php
<?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:

app/Events/OrderPaid.php
php
<?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:

app/Listeners/MarkOrderPaid.php
php
<?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:

S
Stripe marked Order #1035 paid

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:

app/Events/OrderPaid.php
php
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:

EventPayload
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.

Released under the MIT License.