stephpy/timeline-bundle
Symfony2 bundle integrating stephpy/timeline to build timelines/walls for entities. Includes a notification system to count unread items, mark one or all as read, and manage activity streams, with demo app and full documentation available.
Installation
Add the bundle via Composer (note: Laravel doesn't natively support Symfony bundles, but you can integrate the underlying stephpy/timeline library directly):
composer require stephpy/timeline
Basic Timeline Setup
UserActivity):
namespace App\Models;
use Stephpy\Timeline\Annotation\Timeline;
/**
* @Timeline()
*/
class UserActivity
{
// Your fields (e.g., user_id, action, timestamp)
}
First Use Case: Display Timeline
use Stephpy\Timeline\Timeline;
use Stephpy\Timeline\TimelineItem;
Route::get('/timeline', function () {
$timeline = new Timeline();
$timeline->addItem(new TimelineItem(
'User logged in',
'2023-01-01T12:00:00',
'Login action'
));
return view('timeline.index', ['timeline' => $timeline]);
});
Include Timeline JS
Add the timeline library to your resources/views/layouts/app.blade.php:
<script src="https://cdn.jsdelivr.net/npm/timelinejs3@latest/dist/timeline.embed.min.js"></script>
Render Timeline in Blade
<div id="timeline-embed" style="width: 100%; height: 600px;"></div>
<script>
var timeline = new TL.Timeline("timeline-embed", {
embed: true,
json: @json($timeline->toArray())
});
</script>
Entity-Based Timeline Integration
use Stephpy\Timeline\Traits\Timelineable;
class UserActivity extends Model
{
use Timelineable;
protected $timelineItems = [];
}
$activity->addTimelineItem('Commented on post', '2023-01-01');
$activity->save();
$timeline = $activity->getTimeline();
Notification System
// Mark all notifications as read
$this->timelineService->markAllAsRead($userId);
// Get unread count
$unreadCount = $this->timelineService->getUnreadCount($userId);
Custom Timeline Rendering
$timeline = new Timeline();
$timeline->setCustomTemplate('custom_timeline_template');
$timeline->addItem(new TimelineItem(
'Custom Event',
'2023-01-01',
'Custom content',
['class' => 'custom-event']
));
Event-Driven Updates
// In an event listener
public function handle(UserLoggedIn $event)
{
$timeline = new Timeline();
$timeline->addItem(new TimelineItem(
'User logged in',
now()->toDateTimeString(),
'IP: ' . $event->ip
));
$timeline->saveToModel($event->user);
}
Laravel Service Provider: Create a service provider to bind the timeline library:
namespace App\Providers;
use Stephpy\Timeline\Timeline;
use Illuminate\Support\ServiceProvider;
class TimelineServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(Timeline::class, function () {
return new Timeline();
});
}
}
API Integration: Return timeline data as JSON for SPAs:
Route::get('/api/timeline', function () {
$timeline = resolve(Timeline::class);
return response()->json($timeline->toArray());
});
Caching: Cache timeline data for performance:
$timeline = Cache::remember("timeline_{$userId}", now()->addHours(1), function () use ($userId) {
return $this->timelineService->getTimelineForUser($userId);
});
Symfony Dependency Conflicts
stephpy/timeline library and avoid Symfony-specific features.Doctrine ORM Assumptions
interface Timelineable
{
public function getTimelineItems();
public function addTimelineItem(string $title, string $date, string $text);
}
Timeline JS Version Mismatch
timeline.js v3, but CDN versions may vary. Test thoroughly for rendering issues.<script src="https://cdn.jsdelivr.net/npm/timelinejs3@3.1.2/dist/timeline.embed.min.js"></script>
Notification System Limitations
notifiable trait or a separate table.Date Handling Quirks
$date = now()->toDateTimeString(); // Use this instead of Carbon directly
Timeline Data Validation
if (empty($item->getDate()) || empty($item->getTitle())) {
throw new \InvalidArgumentException("Timeline item requires date and title.");
}
Check for JavaScript Errors
timeline.js errors (e.g., missing data or invalid JSON).$timelineData = $timeline->toArray();
\Log::debug('Timeline JSON:', [$timelineData]);
Doctrine Query Debugging
\DB::enableQueryLog();
$timeline = $activity->getTimeline();
\Log::debug(\DB::getQueryLog());
Caching Issues
php artisan cache:clear
php artisan view:clear
Custom Timeline Items
TimelineItem class to add custom fields:
class CustomTimelineItem extends TimelineItem
{
private $customField;
public function __construct(string $title, string $date, string $text, $customField)
{
parent::__construct($title, $date, $text);
$this->customField = $customField;
}
public function getCustomField()
{
return $this->customField;
}
}
Override Timeline Rendering
resources/views/vendor/timeline/items.blade.php:
<div class="custom-timeline-item">
<h3>{{ $item->getTitle() }}</h3>
<p>{{ $item->getText() }}</p>
<small>{{ $item->getDate() }}</small>
</div>
Add Timeline to Existing Models
accessors to dynamically generate timelines:
class UserActivity extends Model
{
public function getTimelineAttribute()
{
return collect($this->items)->map(function ($item) {
return [
'title' => $item->action,
'date' => $item->created_at->toDateTimeString(),
'text' => $item->description,
];
})->toArray();
}
}
Integrate with Laravel Events
How can I help you explore Laravel packages today?