wts-calendar / server-php
PSR-7/PSR-15 REST API server for calendar events, scheduling, validation, ETags, and pluggable PHP storage.
Requires
- php: ^8.2
- ext-json: *
- psr/http-factory: ^1.0
- psr/http-message: ^2.0
- psr/http-server-handler: ^1.0
Requires (Dev)
- nyholm/psr7: ^1.8
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is not auto-updated.
Last update: 2026-09-03 10:40:16 UTC
README
wts-calendar/server-php is the framework-neutral PHP REST API companion for
@wts-calendar/core. It
provides production-oriented PSR-7/PSR-15 HTTP handling, immutable event
contracts, validation, strong ETags, optimistic concurrency, and a replaceable
persistence boundary. It does not require a WTS-hosted backend.
Use it with Angular, React, Vue, React Native, or any client capable of calling JSON HTTP endpoints. Slim can mount the handler directly; Laravel and Symfony can use their standard PSR bridges.
Highlights
- framework-neutral PSR-7, PSR-15, and PSR-17 integration;
- visible-range loading and complete event CRUD routes;
- strong
ETag/If-Matchprotection against lost updates; - RFC 7807-compatible validation and conflict responses;
- all-day, timed, custom-field, resource, and recurrence payload support;
- pluggable persistence for PDO, Doctrine, Eloquent, document stores, or APIs;
- bounded payload, query-window, page-size, and identifier validation;
- no hosted backend, account, telemetry, or vendor-controlled database.
Compatibility
| Component | Supported |
|---|---|
| PHP | 8.2, 8.3, 8.4 and later compatible 8.x releases |
| HTTP messages | PSR-7 2.x |
| Request handler | PSR-15 1.x |
| HTTP factories | PSR-17 1.x |
| WTS browser client | @wts-calendar/core REST data adapter |
Install
composer require wts-calendar/server-php:^1.0
The package supports PHP 8.2 and newer and depends only on standard PSR interfaces at runtime. Your application supplies a PSR-17 response/stream factory; most PSR-compatible frameworks already provide one.
Configure
<?php use WtsCalendar\Server\CalendarApiHandler; use WtsCalendar\Server\CalendarApiOptions; use WtsCalendar\Server\CalendarEventStoreInterface; $handler = new CalendarApiHandler( $container->get(CalendarEventStoreInterface::class), $container->get(Psr\Http\Message\ResponseFactoryInterface::class), $container->get(Psr\Http\Message\StreamFactoryInterface::class), new CalendarApiOptions( requireIfMatchForUpdate: true, requireIfMatchForDelete: true, ), );
Route both the collection and item paths to this PSR-15 handler:
$app->map( ['GET', 'POST', 'PATCH', 'PUT', 'DELETE'], '/api/calendar/events[/{id}]', $handler, );
That route syntax is directly usable with Slim 4. In Symfony or Laravel, expose the same handler through the framework's PSR-7/PSR-15 bridge. Authentication, authorization, CORS, and rate limiting remain normal host middleware.
Implement CalendarEventStoreInterface with PDO, Doctrine, Eloquent, a
document database, or an existing service. InMemoryCalendarEventStore is
included only for examples and tests; it is not durable and must not be used as
production persistence.
Connect the browser package
import { CalendarDataClient, createRestCalendarDataAdapter, } from '@wts-calendar/core/data-adapter-sdk'; const endpoint = 'https://api.example.com/api/calendar/events'; const adapter = createRestCalendarDataAdapter({ url: endpoint, mutationUrl: ({ type, id }) => type === 'create' ? endpoint : `${endpoint}/${encodeURIComponent(id ?? '')}`, headers: async () => ({ authorization: `Bearer ${await accessToken()}`, }), }); const events = new CalendarDataClient(adapter);
All-day values use yyyy-MM-dd. Timed values and query boundaries require ISO
8601 with Z or an explicit UTC offset. Mutation versions are sent as
If-Match entity tags.
HTTP contract
| Method | Route | Purpose |
|---|---|---|
GET |
/api/calendar/events?start=...&end=...&timeZone=... |
Load a bounded visible range |
GET |
/api/calendar/events/{id} |
Load one event and its ETag |
POST |
/api/calendar/events |
Create; returns 201, Location, and ETag |
PATCH or PUT |
/api/calendar/events/{id} |
Replace the event representation |
DELETE |
/api/calendar/events/{id} |
Delete an event |
The handler returns RFC 7807-compatible problem documents. Stale versions use
409 Conflict, matching the WTS REST adapter's conflict result.
Production responsibilities
The host application remains responsible for:
- authentication and per-calendar/per-event authorization;
- tenant isolation, durable storage, transactions, and migrations;
- CORS origins, rate limits, server request-size limits, and observability;
- provider secrets and Google/Microsoft/CalDAV token storage;
- framework exception handling and conflict policy.
Configure a web-server/PHP request limit as well as maxPayloadBytes; the
handler enforces its own bounded stream read, but rejecting oversized requests
before PHP allocates them is more efficient.
Local verification
composer install composer check COMPOSER_ROOT_VERSION=1.0.0 composer archive --format=zip --dir=artifacts
The conformance script checks create, query, strict preconditions, stale-version conflicts, update, validation, delete, ETags, all-day serialization, and route isolation using a real PSR-7 implementation.
For a runnable month calendar with create, edit, and delete dialogs, see
Suman201/calendar-server-php-example.
It mounts this package's real handler and uses a host-provided JSON storage
adapter.
Project links
License
MIT © Suman Mandal.