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

Resolving Bodies When Retrieved ​

Resolve a body when its values must reflect the current model rather than the stored snapshot. Use FeedMedia::body() in the model's feedMedia() method; use Activity Content for bodies stored by toFeed(). Feed Media covers links, files, picture slots, and avatars.

Using Current Values ​

Return a body from feedMedia() to use the model's current values:

app/Models/MenuItem.php
php
use Storyfeed\Body\KeyValue;
use Storyfeed\FeedContext;
use Storyfeed\FeedMedia;

public static function feedMedia(FeedContext $context): ?FeedMedia
{
    return FeedMedia::make()
        ->body(
            KeyValue::make()
                ->items('Portions left', $context->model()?->portions_left),
        );
}
php
use Storyfeed\Body\KeyValue;
use Storyfeed\FeedContext;
use Storyfeed\FeedMedia;

public static function feedMedia(FeedContext $context): ?FeedMedia
{
    return FeedMedia::make(
        body: KeyValue::make(
            items: ['Portions left' => $context->model()?->portions_left],
        ),
    );
}

Stored and resolved bodies share the same payload shape. When toFeed() and feedMedia() both return bodies, the item includes both, with stored bodies first. Your renderer controls the layout.

Choosing Stored or Current Values ​

Choose when a value is decided:

MethodWhen It RunsValue
->data(…) on the activitywhen the activity is publishedfrozen at publication
->body(…) on FeedEntity in toFeed()whenever the model is savedstored and updated with the model
->body(…) on FeedMedia in feedMedia()whenever the feed is retrievedbuilt from current values and never stored

See Computed Values in the Feed for publication-time facts and counts computed on retrieval.

Deferring Body Construction ​

The resolver runs whenever the feed is retrieved. Pass a closure to defer building the body until the payload needs it:

app/Models/MenuItem.php
php
use Storyfeed\Body\KeyValue;
use Storyfeed\FeedContext;
use Storyfeed\FeedMedia;

public static function feedMedia(FeedContext $context): ?FeedMedia
{
    return FeedMedia::make()->body(
        fn (): KeyValue => KeyValue::make()
            ->items('Portions left', $context->model()?->portions_left),
    );
}
php
use Storyfeed\Body\KeyValue;
use Storyfeed\FeedContext;
use Storyfeed\FeedMedia;

public static function feedMedia(FeedContext $context): ?FeedMedia
{
    return FeedMedia::make(
        body: fn (): KeyValue => KeyValue::make(
            items: ['Portions left' => $context->model()?->portions_left],
        ),
    );
}

Loading models takes one query per model class on the page. If the resolver throws, Storyfeed reports the error once per class and omits that body. The activity keeps its label, link, and other bodies. Use a closure when the body needs current model data; bodies built from the snapshot can be passed directly.

Accessing Resolver Data ​

The resolver runs for every entity on the page. Use $context->data() for the snapshot or $context->model() for the current model. The latter loads all models of that class on the page together. Pass relations to $context->model(with: […]) to load them together too. A query such as $model->orders()->count() runs once per entity, so use a counter column on the model to avoid repeated queries.

Released under the MIT License.