stephpy/timeline
Laravel package for recording and displaying chronological “timeline” events on your models. Add entries like notes, status changes, and actions, then query and render them in order for activity feeds and audit-style history.
Installation:
composer require stephpy/timeline
Publish the config (optional):
php artisan vendor:publish --provider="Stephpy\Timeline\TimelineServiceProvider"
First Use Case: Create a timeline in a controller:
use Stephpy\Timeline\Timeline;
public function showTimeline()
{
$timeline = Timeline::create()
->addEntry('2023-01-15', 'User registered', ['user_id' => 123])
->addEntry('2023-01-16', 'First purchase', ['amount' => 99.99]);
return view('timeline.view', ['timeline' => $timeline]);
}
Blade Rendering: Use the included Blade directive:
@timeline($timeline)
Or customize with a view:
@include('timeline::default', ['timeline' => $timeline])
Event-Based Timelines:
// In an event listener
public function handle(OrderShipped $event)
{
Timeline::create()
->addEntry(now(), 'Order shipped', ['order_id' => $event->order->id])
->save(); // Persists to database if configured
}
Dynamic Grouping:
$timeline = Timeline::create()
->groupBy('type') // Groups entries by metadata key
->addEntry(..., ['type' => 'payment'])
->addEntry(..., ['type' => 'notification']);
Integration with Eloquent:
// Fetch timeline from a model
$user = User::find(1);
$timeline = $user->timeline()->get(); // Assumes `hasMany` relationship
Custom Entry Classes:
class CustomEntry extends \Stephpy\Timeline\Entry
{
public function getIcon()
{
return '✉️';
}
}
Timeline::create()->addEntry(new CustomEntry(...));
Pagination:
$timeline = Timeline::create()->paginate(10);
Conditional Rendering:
@timeline($timeline, [
'show_dates' => true,
'group_by' => 'category',
'template' => 'custom.timeline'
])
<!-- Register custom component -->
@php
view()->share('timelineComponent', function ($timeline) {
return \Stephpy\Timeline\Blade::render($timeline, 'custom.view');
});
@endphp
<!-- Usage -->
@timelineComponent($timeline)
Date Handling:
addEntry() are Carbon instances or ISO strings. Ambiguous formats may cause sorting issues.now() or Carbon::parse() for consistency.Metadata Overwrite:
addEntry() calls with the same key overwrite metadata. Use arrays for cumulative data:
->addEntry(..., ['tags' => ['new', 'old']]) // Merges if configured
Grouping Quirks:
groupBy() requires metadata keys to exist in all entries. Use groupBy(fn($entry) => $entry->metadata['key'] ?? 'default') for fallback.Database Persistence:
php artisan vendor:publish --tag=timeline-migrations
php artisan migrate
dd($timeline->getEntries()->toArray());
dd(config('timeline'));
default_template, date_format, enable_persistence.Custom Templates:
resources/views/vendor/timeline/default.blade.php.@inject('timeline', 'Stephpy\Timeline\Timeline') in custom views.Event Listeners:
TimelineSaved event to trigger actions post-save:
Timeline::saved(function ($timeline) {
// Send notification, log, etc.
});
Filtering:
filter() method with closures:
$timeline->filter(fn($entry) => $entry->metadata['status'] === 'active');
Performance:
->limit(100) or lazy-load entries:
$timeline->getEntries()->take(50);
How can I help you explore Laravel packages today?