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

Repeating Activities ​

When a verb repeats on the same object, keep every activity or call keepLatest() on the verb to keep only the latest.

Choosing a Storage Policy ​

Suppose an order is placed, confirmed, amended, and placed again. Choose whether to keep every activity or the latest for each verb:

RequestFull TimelineLatest Activity per Verb
first placementappend placedreplace placed
confirmationappend confirmedreplace confirmed
placed again after an amendmentappend another placedreplace the earlier placed
visible rows afterwardfirst placement, confirmation, second placementconfirmation, second placement

Keeping Every Occurrence ​

To keep the full timeline, publish the transition's verb in the controller on each request:

app/Http/Controllers/OrderTransitionController.php
php
<?php

namespace App\Http\Controllers;

use App\Models\Order;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Storyfeed\Facades\Storyfeed;

class OrderTransitionController extends Controller
{
    // Route::post('orders/{order}/{verb}', OrderTransitionController::class)
    //     ->whereIn('verb', ['place', 'confirm'])
    public function __invoke(
        Request $request,
        Order $order,
        string $verb,
    ): RedirectResponse {
        $order->update(['status' => $verb]);

        Storyfeed::activity()
            ->by($request->user())
            ->action($verb, $order)
            ->to($verb === 'place' ? $order->shop : null)
            ->publish();

        return back();
    }
}
php
<?php

namespace App\Http\Controllers;

use App\Models\Order;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Storyfeed\Facades\Storyfeed;

class OrderTransitionController extends Controller
{
    // Route::post('orders/{order}/{verb}', OrderTransitionController::class)
    //     ->whereIn('verb', ['place', 'confirm'])
    public function __invoke(
        Request $request,
        Order $order,
        string $verb,
    ): RedirectResponse {
        $order->update(['status' => $verb]);

        Storyfeed::record(
            verb: $verb,
            object: $order,
            actor: $request->user(),
            target: $verb === 'place' ? $order->shop : null,
        );

        return back();
    }
}

Retrieve the order's timeline in log mode:

app/Http/Controllers/OrderController.phpshow()
php
use Storyfeed\Facades\Storyfeed;

$timeline = Storyfeed::feed()->involving($order)->log()->get();

Keeping the Latest Occurrence ​

Call keepLatest() on each verb to replace its earlier activities. The controller publishes as before; the query below retrieves the feed in live mode:

routes/feed.php
php
use App\Models\Order;
use Storyfeed\Facades\Story;

Story::for(Order::class)->verb('place')
    ->headline(':actor placed :object with :target')
    ->keepLatest(); // removes earlier placements from every feed

Story::for(Order::class)->verb('confirm')
    ->headline(':actor confirmed :object')
    ->keepLatest();
app/Http/Controllers/OrderController.phpshow()
php
use Storyfeed\Facades\Storyfeed;

$latest = Storyfeed::feed()->involving($order)->live()->get();

For this order, the feed keeps the latest activity for each verb.

Replaced activities disappear from every feed, including log(). Keep every activity if any page needs the full timeline.

See Keeping the Latest Activity for matching roles and time limits.

Released under the MIT License.