Installation Add the bundle via Composer:
composer require comsa/sulu-reservations-bundle
Register the bundle in config/bundles.php:
return [
// ...
Comsa\SuluReservationsBundle\SuluReservationsBundle::class => ['all' => true],
];
Database Migration Run migrations to create the required tables:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
Basic Configuration
Configure the bundle in config/packages/comsa_sulu_reservations.yaml:
comsa_sulu_reservations:
reservation_types: ['default'] # Define your reservation types
default_duration: 30 # Default duration in minutes
First Use Case: Creating a Reservation
Use the ReservationManager service to create a reservation:
use Comsa\SuluReservationsBundle\Manager\ReservationManager;
class SomeController
{
public function __construct(private ReservationManager $reservationManager) {}
public function createReservation()
{
$reservation = $this->reservationManager->create(
'default', // Reservation type
'[email protected]', // User identifier
new \DateTime('+1 hour'), // Start time
60 // Duration in minutes
);
return new JsonResponse(['success' => true, 'reservation_id' => $reservation->getId()]);
}
}
Reservation Creation & Validation
ReservationManager for creation with validation hooks:
$reservation = $this->reservationManager->create(
'type',
'[email protected]',
$startTime,
$duration,
['metadata' => ['custom_field' => 'value']] // Optional metadata
);
ReservationCreateEvent).Time Slot Management
$availableSlots = $this->reservationManager->getAvailableSlots(
'type',
new \DateTime('today'),
new \DateTime('+2 days'),
30 // Slot duration in minutes
);
$this->reservationManager->blockSlot('type', $startTime, $duration);
$this->reservationManager->unblockSlot($reservationId);
User & Resource Association
$reservation->setUser('[email protected]');
$reservation->setResource('room-101');
$this->reservationManager->save($reservation);
Recurring Reservations
$recurringReservation = $this->reservationManager->createRecurring(
'type',
'[email protected]',
'0 9 * * 1-5', // Cron syntax (9 AM, Mon-Fri)
60, // Duration
new \DateTime('2023-10-01'), // Start date
new \DateTime('2023-12-31') // End date
);
Integration with Sulu CMS
ReservationAdmin trait to embed reservations in Sulu admin panels:
use Comsa\SuluReservationsBundle\Admin\ReservationAdmin;
class MyAdmin extends AbstractAdmin
{
use ReservationAdmin;
// ...
}
ReservationClient (if provided) or fetch data via REST/GraphQL.ReservationCreatedEvent to trigger emails/SMS:
$eventDispatcher->addListener(ReservationCreatedEvent::class, function (ReservationCreatedEvent $event) {
// Send notification
});
translations/ for multi-language support.Time Zone Handling
start_time and duration are in the same time zone as your application.default_timezone in config/packages/comsa_sulu_reservations.yaml:
comsa_sulu_reservations:
default_timezone: 'Europe/Berlin'
Overlapping Reservations
$this->reservationManager->validateOverlap('type', $startTime, $duration);
Recurring Reservation Edge Cases
ReservationRecurrenceFilter to exclude dates:
$filter = new ReservationRecurrenceFilter();
$filter->excludeDates(['2023-12-25']); // Skip Christmas
$this->reservationManager->createRecurring(..., $filter);
Performance with Large Datasets
$reservations = $this->reservationManager->findBy([
'type' => 'default',
'startTime' => ['>=', new \DateTime('-7 days')],
], 10, 0); // Limit 10, offset 0
Caching
getAvailableSlots() results if the data changes infrequently:
$cacheKey = 'available_slots_' . $type . '_' . $startTime->format('Y-m-d');
$slots = $cache->get($cacheKey, function () use ($type, $startTime) {
return $this->reservationManager->getAvailableSlots($type, $startTime, '+1 day', 30);
});
Enable SQL Logging
Add to .env:
DOCTRINE_DDL_LOGGING=1
DOCTRINE_DDL_LOGGING_FORMAT=natural
Event Debugging Dump events in a listener:
$eventDispatcher->addListener(ReservationCreatedEvent::class, function (ReservationCreatedEvent $event) {
dump($event->getReservation()->toArray());
});
Common Errors
reservation_types config.php bin/console doctrine:schema:validate after migrations.Custom Reservation Types
Extend the ReservationType class to add fields:
class CustomReservationType extends ReservationType
{
public function getAdditionalFields()
{
return [
'max_guests' => ['type' => 'integer', 'required' => true],
];
}
}
Register in config:
comsa_sulu_reservations:
reservation_types:
custom: Comsa\SuluReservationsBundle\Entity\CustomReservationType
Custom Validation
Subscribe to ReservationCreateEvent:
$eventDispatcher->addListener(ReservationCreateEvent::class, function (ReservationCreateEvent $event) {
if ($event->getReservation()->getType() === 'vip' && $event->getReservation()->getDuration() > 120) {
throw new \RuntimeException('VIP reservations cannot exceed 2 hours.');
}
});
Custom Storage
Override the ReservationRepository to use a custom storage backend (e.g., Elasticsearch):
services:
Comsa\SuluReservationsBundle\Repository\ReservationRepository:
class: App\Repository\CustomReservationRepository
arguments: ['@doctrine.orm.entity_manager']
UI Customization
Override Twig templates in templates/comsa_sulu_reservations/ to modify the admin interface.
How can I help you explore Laravel packages today?