Skip to main content
Version: 2.x

← Previous · Back to README · Next →

Eloquent

FeedObserver::saving() runs on every event-enabled model create(), update(), or save(). After PR #335, it assigns $feed->slug = $feed->title only when $feed->isDirty('slug') is false. SlugCast applies Str::slug() to both generated and manually supplied slugs. For example, Products becomes products.

An explicitly changed slug is preserved for that save, including when title changes at the same time. This does not make a custom slug permanent: on a later ordinary save, an unchanged slug is recalculated from title, even when the title is unchanged. Assigning the same slug, or a value that normalizes to the current slug, does not count as a change.

The observer reads the current title property, including modern and legacy accessors, after any setters already applied. It does not read the raw stored title or guarantee the final value written to the database. An accessor returning Display: Stored: Product Catalog produces display-stored-product-catalog. Keep display-only formatting in a separate accessor if it should not affect slugs.

saveQuietly() and saves inside withoutEvents() skip the observer. Changing title this way leaves the previous slug unchanged unless the application assigns it explicitly. Use a normal save when events are wanted. For a quiet save with the same derivation as the observer:

use DragonCode\LaravelFeed\Models\Feed;

$feed = Feed::query()->findOrFail(42);
$feed->title = 'New Title';
$feed->slug = $feed->title;
$feed->saveQuietly();

If a later saving listener, or a creating or updating listener, changes title, the package does not recalculate the slug afterward. Prefer setting the title before saving or using a title mutator. If a listener must change it later, assign $feed->slug = $feed->title immediately after that change in the same listener; do not call save() recursively. Check the listener order in application tests.

When saving a partially selected model without an explicitly changed slug, include title and every attribute required by its accessor. A missing title does not disable slug generation. Query Builder bulk inserts and updates do not run this observer; maintain both values explicitly for those writes. Preserve the inherited observer and casts in custom models.

Keep stored slugs distinct and non-empty for selected and scheduled feeds. When deriving slugs from titles, choose titles that normalize to distinct, non-empty values. An empty stored slug cannot be selected. Multiple non-deleted registrations with the same slug cause Illuminate\Database\MultipleRecordsFoundException on lookup; no suffix is added automatically.

Custom feed registration model​

Set feeds.model to an application model when feed registration records need additional columns, casts, relationships, or methods. The custom model must extend DragonCode\LaravelFeed\Models\Feed.

namespace App\Models;

use DragonCode\LaravelFeed\Models\Feed as BaseFeed;

class Feed extends BaseFeed
{
protected $fillable = [
'slug',
'class',
'title',
'expression',
'is_active',
'last_activity',
'is_foo',
'is_bar',
];

protected function casts(): array
{
return [
...parent::casts(),
'is_foo' => 'boolean',
'is_bar' => 'boolean',
];
}
}

Register the model in config/feeds.php:

'model' => App\Models\Feed::class,

Add the custom columns to the feeds table in an application migration. Keep every attribute accepted by mass assignment in $fillable.

FeedQuery uses the configured model for create, find, list, update, delete, and restore operations. Pass application-specific values through extra when creating a record. These values are applied last and can override the method arguments:

$feed = app(FeedQuery::class)->create(
class: SomeFeed::class,
title: 'Some',
expression: '0 */12 * * *',
extra: [
'slug' => 'Custom Some',
'is_foo' => true,
'is_bar' => true,
]
);

This creates the registration with slug custom-some. Model create() and update() also accept an explicit slug; updating title and slug together preserves the changed slug for that save.

The application model can also use the regular Eloquent API:

use App\Models\Feed;

$feed = Feed::create([
'class' => SomeFeed::class,
'title' => 'Some',
'expression' => '0 */12 * * *',
'is_active' => true,
'is_foo' => true,
'is_bar' => true,
]);
note

The configured model is resolved at runtime. Static analysis sees the result of FeedQuery::create() as the package base model. Use App\Models\Feed::create() or an explicit local type when autocomplete for application-specific properties is required.

Chunk size​

Database queries use chunks, which are 1000 items by default. You can change this by overriding the chunkSize method:

use DragonCode\LaravelFeed\Feeds\Feed;

class UserFeed extends Feed
{
public function chunkSize(): int
{
return 500;
}
}

See Also​