⚠️ Documentation Under Review: This documentation is currently being updated and verified against the actual implementation. Some information may be incorrect or incomplete. Please verify all code examples against the actual source code before use.
The Neuron CMS includes a comprehensive event management system for creating and managing calendar events. This feature enables you to create events with dates, times, locations, and categories, perfect for conferences, meetings, workshops, and other scheduled activities.
Location: Neuron\Cms\Models\Event
The Event model extends Neuron\Orm\Model and represents calendar events:
use Neuron\Orm\Model;
use Neuron\Orm\Attributes\Table;
use Neuron\Orm\Attributes\BelongsTo;
#[Table( 'events' )]
class Event extends Model
{
#[BelongsTo( User::class, 'created_by' )]
protected ?User $creator;
#[BelongsTo( EventCategory::class, 'category_id' )]
protected ?EventCategory $category;
}
| Property | Type | Description |
|---|---|---|
id |
int |
Event ID (auto-increment) |
title |
string |
Event title |
slug |
string |
URL-friendly identifier |
description |
string |
Short event description |
content_raw |
string |
Editor.js JSON content |
location |
string |
Event location/venue |
start_date |
DateTimeImmutable |
Event start date/time |
end_date |
DateTimeImmutable |
Event end date/time (optional) |
all_day |
bool |
All-day event flag |
category_id |
int |
Event category ID |
status |
string |
Publication status |
featured_image |
string |
Featured image URL |
organizer |
string |
Event organizer name |
contact_email |
string |
Contact email address |
contact_phone |
string |
Contact phone number |
created_by |
int |
Creator user ID |
view_count |
int |
Number of views |
created_at |
DateTimeImmutable |
Creation timestamp |
updated_at |
DateTimeImmutable |
Last update timestamp |
Events can be organized into categories for better organization:
use Neuron\Orm\Model;
use Neuron\Orm\Attributes\Table;
use Neuron\Orm\Attributes\HasMany;
#[Table( 'event_categories' )]
class EventCategory extends Model
{
#[HasMany( Event::class, 'category_id' )]
protected array $events;
}
Events use the same status workflow as content:
use Neuron\Cms\Enums\ContentStatus;
ContentStatus::Draft // Not publicly visible
ContentStatus::Published // Live and accessible
use Neuron\Cms\Models\Event;
use Neuron\Cms\Repositories\DatabaseEventRepository;
use Neuron\Cms\Enums\ContentStatus;
$event = new Event();
$event->setTitle( 'Annual Conference 2025' );
$event->setSlug( 'annual-conference-2025' );
$event->setDescription( 'Join us for our annual conference' );
$event->setLocation( 'Convention Center, Main Hall' );
$event->setStartDate( new DateTimeImmutable( '2025-06-15 09:00:00' ) );
$event->setEndDate( new DateTimeImmutable( '2025-06-17 17:00:00' ) );
$event->setAllDay( false );
$event->setOrganizer( 'Tech Community' );
$event->setContactEmail( '[email protected]' );
$event->setStatus( ContentStatus::Published );
$repository = new DatabaseEventRepository( $database );
$repository->save( $event );
For all-day events, set the flag and use date-only times:
$event->setAllDay( true );
$event->setStartDate( new DateTimeImmutable( '2025-06-15 00:00:00' ) );
$event->setEndDate( new DateTimeImmutable( '2025-06-15 23:59:59' ) );
Creates new events with automatic slug generation:
use Neuron\Cms\Services\Event\Creator;
use Neuron\Cms\Repositories\DatabaseEventRepository;
$creator = new Creator( $eventRepository, $categoryRepository );
$event = $creator->create( title: 'Workshop: PHP Best Practices',
startDate: new DateTimeImmutable( '2025-07-01 14:00:00' ),
endDate: new DateTimeImmutable( '2025-07-01 17:00:00' ),
location: 'Room 101',
categoryId: 3,
status: ContentStatus::Published
);
Updates existing events:
use Neuron\Cms\Services\Event\Updater;
$updater = new Updater( $eventRepository );
$updater->update( $event,
title: 'Updated Workshop Title',
location: 'Room 202' );
$repository = new DatabaseEventRepository( $settings );
// Get upcoming events
$upcomingEvents = $repository->getUpcoming( limit: 10 );
// Get events for specific date range
$events = $repository->getByDateRange( startDate: new DateTimeImmutable( '2025-06-01' ),
endDate: new DateTimeImmutable( '2025-06-30' )
);
// Get events by category
$categoryEvents = $repository->getByCategory( $categoryId );
// Get past events
$pastEvents = $repository->getPast( limit: 10 );
// Check if event has passed
if( $event->getEndDate() < new DateTimeImmutable() )
{
// Event has ended
}
// In controller
$events = $repository->findUpcoming();
// In view
foreach( $events as $event )
{
echo '<article>';
echo '<h3>' . htmlspecialchars( $event->getTitle() ) . '</h3>';
echo '<time>' . $event->getStartDate()->format( 'F j, Y g:i A' ) . '</time>';
echo '<p>' . htmlspecialchars( $event->getLocation() ) . '</p>';
echo '</article>';
}
Events can be integrated with calendar libraries:
// Generate iCal format
$ical = "BEGIN:VCALENDAR\r\n";
$ical .= "VERSION:2.0\r\n";
$ical .= "BEGIN:VEVENT\r\n";
$ical .= "SUMMARY:" . $event->getTitle() . "\r\n";
$ical .= "DTSTART:" . $event->getStartDate()->format( 'Ymd\THis' ) . "\r\n";
$ical .= "DTEND:" . $event->getEndDate()->format( 'Ymd\THis' ) . "\r\n";
$ical .= "LOCATION:" . $event->getLocation() . "\r\n";
$ical .= "END:VEVENT\r\n";
$ical .= "END:VCALENDAR\r\n";
Events are stored in two tables created by migrations:
Created by 20251221000001_create_events_table.php:
Created by 20251221000000_create_event_categories_table.php:
Register routes for event display:
# config/routes.yaml
events:
method: GET
route: /events
controller: App\Controllers\Events@index
event_detail:
method: GET
route: /events/{slug}
controller: App\Controllers\Events@show
events_calendar:
method: GET
route: /events/calendar/{year}/{month}
controller: App\Controllers\Events@calendar
DateTimeImmutable for dates<?php
namespace App\Controllers;
use Neuron\Cms\Repositories\DatabaseEventRepository;
use Neuron\Cms\Services\Event\EventCreator;
class EventsController extends Controller
{
private DatabaseEventRepository $repository;
public function __construct( DatabaseEventRepository $repository )
{
$this->repository = $repository;
}
public function index()
{
$upcoming = $this->repository->getUpcoming( limit: 20 );
return $this->view( 'events/index', [
'events' => $upcoming,
'title' => 'Upcoming Events'
] );
}
public function show( string $slug )
{
$event = $this->repository->findBySlug( $slug );
if( !$event )
{
return $this->notFound();
}
// Increment view count
$event->incrementViewCount();
$this->repository->save( $event );
return $this->view( 'events/show', [
'event' => $event
] );
}
public function calendar( int $year, int $month )
{
$startDate = new DateTimeImmutable( "$year-$month-01" );
$endDate = $startDate->modify( 'last day of this month' );
$events = $this->repository->getByDateRange( $startDate, $endDate );
return $this->view( 'events/calendar', [
'events' => $events,
'year' => $year,
'month' => $month
] );
}
}