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.
- 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.
| 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 |
composer require wts-calendar/server-php:^1.0The 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.
<?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.
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.
| 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.
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.
composer install
composer check
COMPOSER_ROOT_VERSION=1.0.0 composer archive --format=zip --dir=artifactsThe 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.
MIT © Suman Mandal.