Skip to content

Latest commit

 

History

History
135 lines (96 loc) · 4.8 KB

File metadata and controls

135 lines (96 loc) · 4.8 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

fishyboat21/simple-api is a minimal PHP 8.4+ library for building JSON HTTP APIs using a per-file endpoint pattern. Each API endpoint is its own PSR-4 class file — the file path maps to the URL route. A pre-built trie-based route cache provides O(depth) route matching with zero filesystem scanning at runtime.

No build step, no framework, no ORM — just Composer autoloading.

Namespace & Autoloading

PSR-4 mapping: Fishyboat21\SimpleApi\src/

After adding new classes under src/, run:

composer dump-autoload

After adding or changing endpoint handlers, regenerate the route cache:

composer route:generate

Core Architecture

Entry Point: SimpleApi (src/SimpleApi.php)

The main application class. Replaces the deprecated BaseAPI.

  1. Loads route cache via require (opcache-friendly)
  2. Handles CORS preflight (configurable via CorsConfig)
  3. Matches request to handler class via RouteCollection (trie)
  4. Dispatches to handler, applies CORS headers, sends JSON response

Error handling:

  • HttpException subclasses (404, 405) → their message is safe to expose
  • Throwable → generic "Internal Server Error" (real message logged server-side via optional PSR-3 logger, never leaked)

Per-File Endpoint Pattern

Endpoint classes live under src/Api/ (in the consuming project). The filesystem path is the URL path:

src/Api/Health/Index.php       →  GET  /api/health
src/Api/Users/Index.php        →  GET,POST /api/users
src/Api/Users/_id/Index.php    →  GET,PUT,DELETE /api/users/{id}
src/Api/Users/_id/Posts.php    →  GET /api/users/{id}/posts

Convention rules:

  • Strip src/Api/ prefix and .php suffix
  • Convert to lowercase, / separators
  • Trailing /Index segment is removed (resource root)
  • Segments starting with _ become path parameters: _id{id}
  • HTTP method declared via #[Route(Method::GET)] attribute

Each endpoint class implements ApiHandler (marker interface) and uses #[Route] attributes:

#[Route(Method::GET)]
class Index implements ApiHandler
{
    public function handle(Request $request): Response
    {
        return Response::ok(['data' => ...]);
    }
}

Route Cache (storage/routes.php — auto-generated)

Generated by composer route:generate. A nested-array trie loaded via require:

return [
    'users' => [
        '__handlers' => ['GET' => ['App\Api\Users\Index', 'list'], ...],
        '*' => ['__name' => 'id', '__handlers' => ['GET' => ['...', 'show'], ...]],
    ],
];

Do not edit by hand. Regenerate after adding/changing endpoint files.

Router (src/Router/)

  • RouteCollection — Trie matcher, O(depth), static segment checked first (fast path), * for params
  • RouteScanner — Scans src/Api/ for ApiHandler classes, reads #[Route] via reflection, builds trie
  • RouteMatch — DTO: handlerClass, handlerMethod, params
  • RouteGenerateCommand — CLI entry for vendor/bin/simple-api route:generate

Request / Response (src/Http/)

  • RequestfromGlobals() / fromParts(), lazy JSON body parsing, query/body/header accessors, immutable path params via withAttribute()
  • Response — PHP 8.4 property hooks, factory methods: ok(), created(), noContent(), notFound(), error(), withHeader() for CORS/custom headers

CORS (src/Cors.php + src/Config/CorsConfig.php)

Configurable: allowed origins, methods, headers, credentials, max age. Preflight returns proper Access-Control-Allow-* headers. Response headers applied after dispatch.

Exception Hierarchy (src/Exception/)

HttpException (abstract)
├── NotFoundException         → 404
└── MethodNotAllowedException → 405

Attribute (src/Attribute/Route.php)

#[Route(Method::GET)] — repeatable, usable on classes (targets handle()) or methods (targets that method).

Deprecated (Backward Compat)

Old Replacement
BaseAPI SimpleApi
addHandler() #[Route] + ApiHandler
IResponse Response
ResponseError Response::error()
ResponseSuccess Response::ok()

PHP Version

Requires PHP >=8.4. Uses PHP 8.4 property hooks and readonly classes.

Key Performance Properties

  • Route cache loaded via require — opcache caches to shared memory
  • Trie matching — O(depth), typically 2-5 array lookups per request
  • Lazy handler loading — PSR-4 autoloader fires only after route match
  • Lazy body parsingphp://input read only when handler calls body()
  • No middleware stack — fixed pipeline: CORS → route → dispatch → send
  • Zero filesystem scanning at runtime — route cache is pre-built