Common Scenarios
Scenario 1: Public content read API
Goal: expose posts read-only for frontend app.
Resource::make('articles')
->restNamespace('better-route/v1')
->sourceCpt('post')
->allow(['list', 'get'])
->fields(['id', 'title', 'slug', 'excerpt', 'date'])
->filters(['after', 'before'])
->filterSchema(['after' => 'date', 'before' => 'date'])
->sort(['date', 'id'])
->policy(['public' => true])
->register();
Notes:
- strict query parsing keeps contract stable
- default status visibility keeps drafts out
Scenario 2: Protected write API with idempotency + optimistic lock
Goal: safe concurrent updates from external writer.
$router->middleware([
new IdempotencyMiddleware(new TransientIdempotencyStore(), ttlSeconds: 300, requireKey: true),
new OptimisticLockMiddleware(new CallbackOptimisticLockVersionResolver($resolveVersion)),
]);
$router->patch('/orders/(?P<id>\d+)', $updateOrder)
->permission(static fn (): bool => current_user_can('edit_posts'));
Expected failures:
- missing idempotency key ->
400 idempotency_key_required - stale version ->
412 optimistic_lock_failed
Scenario 3: OpenAPI endpoint from mixed sources
Goal: one document from router + CPT + table resources.
OpenApiRouteRegistrar::register(
restNamespace: 'better-route/v1',
contractsProvider: static fn (): array => OpenApiRouteRegistrar::contractsFromSources([
$router,
$articlesResource,
$rawArticlesResource,
]),
options: ['title' => 'Better Route API', 'version' => 'v0.2.0']
);
Scenario 4: Metrics + audit baseline
Goal: produce operational signals for every request.
$router->middleware([
new MetricsMiddleware(new PrometheusMetricSink()),
new AuditMiddleware(new ErrorLogAuditLogger()),
]);
Validation:
- counters and durations are emitted
- audit event has requestId + statusCode + outcome