A RESTful API built with Laravel 12 for managing events, attendees, and bookings.
This improved version keeps the same core API usage, but now applies cleaner architecture and stronger consistency rules:
- Service + Repository layering with repository contracts (Dependency Inversion)
- Centralized API exception mapping for consistent JSON error responses
- Better schema/validation alignment (nullable/unique/composite constraints)
- Typed method signatures across services and repositories for clearer contracts
The API allows you to:
- Create, update, delete, and list events (paginated)
- Register and manage attendees
- Create and manage bookings
- Prevent overbooking and duplicate bookings
- Validate incoming requests and return structured JSON responses
If your machine already has Laravel Herd installed:
composer install
cp .env.example .env
php artisan key:generate
type nul > database\database.sqlite # Windows
php artisan migrate --seed
php artisan testThen open:
http://event-booking-api-improved.test/api
Use the full setup sections below if this is your first time configuring the project.
- Framework: Laravel 12 (PHP 8.2+)
- Local Development: Laravel Herd (required)
- Database: SQLite
- Testing: PHPUnit + Laravel testing tools
- API Testing: Postman (optional)
Before you begin, install:
- Laravel Herd
- Provides PHP, Composer, and automatic .test domain routing
- TablePlus (optional)
- Used to inspect and manage the SQLite database
After project setup:
- Open TablePlus β Create a new connection
- Select SQLite
- Choose the database/database.sqlite file
- Connect and verify tables (events, attendees, bookings)
Clone into your Herd directory so Herd auto-serves the project:
cd ~/Herd
# Windows example: cd C:\Users\YourUsername\Herd
git clone <your-repository-url>
cd event-booking-api-improvedIf this repository is already on your machine, just open it and continue.
code .composer installcp .env.example .env
# Windows (cmd): copy .env.example .envphp artisan key:generatetouch database/database.sqlite
# Windows: type nul > database\database.sqliteSet:
DB_CONNECTION=sqlite
DB_DATABASE=database/database.sqlitephp artisan migrate --seedIf you are upgrading from an older local schema, use:
php artisan migrate:fresh --seedWith Herd, the app is available at:
http://event-booking-api-improved.test
API base:
http://event-booking-api-improved.test/api
Routes are registered in routes/api.php.
| Action | Method | URL | Body / Params |
|---|---|---|---|
| List events | GET | /api/events | Optional: ?page=2, ?country=UK |
| Get single event | GET | /api/events/{id} | β |
| Create event | POST | /api/events | { "title": "Concert", "description": "...", "date": "2026-02-20", "country": "UK", "capacity": 100 } |
| Update event | PUT/PATCH | /api/events/{id} | Partial updates supported |
| Delete event | DELETE | /api/events/{id} | β |
Event field rules:
- title: required, string, max 255
- description: nullable, string
- date: required, date
- country: required, string
- capacity: required, integer, min 1
| Action | Method | URL | Body |
|---|---|---|---|
| List attendees | GET | /api/attendees | β |
| Get attendee | GET | /api/attendees/{id} | β |
| Register attendee | POST | /api/attendees | { "name": "Dan Wrigley", "email": "dan@example.com" } |
| Update attendee | PUT/PATCH | /api/attendees/{id} | Partial updates supported |
| Delete attendee | DELETE | /api/attendees/{id} | β |
Attendee field rules:
- name: required on create, string
- email: required on create, valid email, unique
| Action | Method | URL | Body |
|---|---|---|---|
| List bookings | GET | /api/bookings | Optional: ?attendee_id=1 |
| Get booking | GET | /api/bookings/{id} | β |
| Create booking | POST | /api/bookings | { "event_id": 1, "attendee_id": 3 } |
| Delete booking | DELETE | /api/bookings/{id} | β |
Booking protections:
- Overbooking is blocked when event capacity is reached
- Duplicate attendee booking for the same event is blocked
- Composite unique constraint enforces this rule at DB level too
The improved version centralizes API exception mapping in bootstrap configuration.
Typical responses:
- 422: validation failures (Form Requests)
- 400: business rule violations (for example, event full / duplicate booking)
- 404: resource or route not found (
Resource not found) - 500: unexpected server errors on API routes
This makes controller actions thinner and response behavior consistent.
The project now follows a clearer layering approach:
- Controllers: HTTP orchestration only
- Services: business rules
- Repositories: persistence logic
- Repository Contracts: abstractions consumed by services/controllers
Why this was applied:
- Dependency Inversion: high-level modules depend on interfaces, not concrete repositories
- Better testability: contracts are easier to mock/substitute
- Consistency: shared exception strategy instead of repetitive try/catch per controller
Run all tests:
php artisan testRun a specific class:
php artisan test --filter=BookingTest
php artisan test --filter=BookingServiceTest- Open the shared collection here: Event Booking API Postman Collection
How to use:
- Import the collection into Postman.
- Set your local base URL to
http://event-booking-api-improved.test/api. - Run
GET /eventsfirst to confirm connectivity. - Then run create/update/delete requests for events, attendees, and bookings.
app/
ββ Http/
β ββ Controllers/
β β ββ EventController.php
β β ββ AttendeeController.php
β β ββ BookingController.php
β ββ Requests/
β ββ StoreEventRequest.php
β ββ UpdateEventRequest.php
β ββ StoreAttendeeRequest.php
β ββ UpdateAttendeeRequest.php
β ββ StoreBookingRequest.php
ββ Models/
β ββ Event.php
β ββ Attendee.php
β ββ Booking.php
β ββ User.php
ββ Repositories/
β ββ Contracts/
β β ββ EventRepositoryInterface.php
β β ββ AttendeeRepositoryInterface.php
β β ββ BookingRepositoryInterface.php
β ββ EventRepository.php
β ββ AttendeeRepository.php
β ββ BookingRepository.php
ββ Services/
ββ EventService.php
ββ AttendeeService.php
ββ BookingService.php
Authentication is not implemented in this project version.
For production usage, Laravel Sanctum would be the natural next step for token-based API auth.
- This is an API-only project (no frontend UI).
- Authentication/authorization is intentionally not implemented.
- Booking creation currently relies on business-rule checks plus DB constraints; high-concurrency locking strategies are not yet implemented.
Open source under the MIT License.