gijsbos / apiserver
API Server
Requires
- gijsbos/classparser: ^2.1.2
- gijsbos/extfuncs: ^1.7
- gijsbos/http: ^1.5
- gijsbos/logging: ^1.4
- gijsbos/php-cli-parser: ^1.1
- gijsbos/stringfuncs: ^1.4.1
Requires (Dev)
- phpunit/phpunit: ^10.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- 1.18
- 1.17.1
- 1.17
- 1.16
- 1.15
- 1.14
- 1.13.3
- 1.13.2
- 1.13.1
- 1.13
- 1.12
- 1.11
- 1.10.1
- 1.10
- 1.9.33
- 1.9.32
- 1.9.31
- 1.9.30
- 1.9.29
- 1.9.28
- 1.9.27
- 1.9.26
- 1.9.25
- 1.9.24
- 1.9.23
- 1.9.22
- 1.9.21
- 1.9.20
- 1.9.19
- 1.9.18
- 1.9.17
- 1.9.16
- 1.9.15
- 1.9.14
- 1.9.13
- 1.9.12
- 1.9.11
- 1.9.10
- 1.9.9
- 1.9.8
- 1.9.7
- 1.9.6
- 1.9.5
- 1.9.4
- 1.9.3
- 1.9.2
- 1.9.1
- 1.9.0
- 1.8.8
- 1.8.7
- 1.8.6
- 1.8.5
- 1.8.4
- 1.8.3
- 1.8.2
- 1.8.0
- 1.7.19
- 1.7.18
- 1.7.17
- 1.7.16
- 1.7.15
- 1.7.14
- 1.7.13
- 1.7.12
- 1.7.11
- 1.7.2
- 1.7.1
- 1.7.0
- 1.6.61
- 1.6.7
- 1.6.6
- 1.6.5
- 1.6.4
- 1.6.3
- 1.6.2
- 1.6.1
- 1.6
- 1.5.25
- 1.5.24
- 1.5.23
- 1.5.22
- 1.5.21
- 1.5.5
- 1.5.4
- 1.5.3
- 1.5.2
- 1.5.1
- 1.5.0
- 1.4.24
- 1.4.23
- 1.4.22
- 1.4.21
- 1.4.20
- 1.4.19
- 1.4.18
- 1.4.17
- 1.4.16
- 1.4.15
- 1.4.14
- 1.4.13
- 1.4.12
- 1.4.11
- 1.4.1
- 1.4.0
- 1.3.9
- 1.3.8
- 1.3.7
- 1.3.6
- 1.3.5
- 1.3.4
- 1.3.3
- 1.3.2
- 1.3.1
- 1.3.0
- 1.2.0
- 1.1.0
- 1.0.0
This package is auto-updated.
Last update: 2026-09-27 12:21:48 UTC
README
Introduction
Lightweight, attribute-driven PHP API Server that simplifies route definition, request validation, and response filtering. It aims to make building structured REST APIs clean, fast, and type-safe, leveraging PHP 8+ attributes.
Requirements
Before running the application, make sure you have the following installed:
- Web Server: Apache or Nginx
- PHP:
>= 8.2 - Composer: for dependency management
Installation
composer require gijsbos/apiserver
Setup
Controllers
Extend your controllers with the RouteController class and create a new route by defining attributes:
- Route(
method,path) or short GetRoute, PostRoute, PutRoute, DeleteRoute, PatchRoute, OptionsRoute. - ReturnFilter(
array) - assoc array containing keys to filter out. - RequiresAuthorization() - extends the ExecuteBeforeRoute, provides simple token checking and extraction.
Route Parameters
Route parameters allow you to inject parameters into your controller method.
PathVariable- Extracts parameters from path that have been defined using curly brackets.RequestParam- Extracts parameters from global variables.RequestHeader- Extracts headers from server headers.
Parameter behaviour can be controlled by both defining union types and optional parameters.
RequestParam|string $id- Expects a string value, when not defined defaults toempty string.RequestParam|int $id- Expects anintvalue, cast tointor defaults toempty string.RequestParam|float $id- Expects anfloatvalue, cast tofloator defaults toempty string.RequestParam|double $id- Expects anintvalue, cast todoubleor defaults toempty string.RequestParam|bool $id- Expects anintvalue, cast toboolor defaults toempty string.
Allowing null values requires you to add the null union type:
RequestParam|string|null $id- Expects a string value, when not defined defaults tonull.
Route parameter options can be defined by defining the object inside the parameter definition:
PathVariable|string $id = new PathVariable(["min" => 0, "max" => 999, "required" => true, "pattern" => "/\d+/", "default" => 1])
The following options can be used:
- min int - minimum value for
intvalues, minimum length forstringvalues. - max int - maximum value for
intvalues, maximum length forstringvalues. - required bool - when true, throws missing error when parameter is not defined (has no effect on PathVariable).
- pattern string - regexp pattern uses to check the value.
- default mixed - fallback value when value is empty.
- values array - permitted values or throws error.
Example
class UserController extends RouteController
{
#[GetRoute('/user/{id}/')]
#[ReturnFilter(['name','id'])]
public function getUser(
PathVariable|string $id = new PathVariable(["min" => 0, "max" => 999, "required" => false]),
RequestParam|string $name = new RequestParam(["min" => 0, "max" => 10, "pattern" => "/^[a-z]+$/", "required" => false, "default" => "john"]),
)
{
return [
"id" => "<$id>",
"name" => $name,
];
}
}
Server
Create a server by defining the following in your index.php. Every request must be rewritten to the index.php file.
try
{
$server = new Server([
"requireHttps" => false, // Must use HTTPS or receive error
"pathPrefix" => "", // Used for subpaths e.g. localhost/mysubpath/
"addServerTime" => false, // Adds code execution time
"addRequestTime" => false, // Adds total server response time
"trustedProxies" => [], // IPs / CIDR ranges of proxies allowed to set X-Forwarded-For and X-Forwarded-Proto
]);
$server->listen();
}
catch(RuntimeException | Exception | TypeError | Throwable $ex)
{
print($ex->getMessage());
}
Request and correlation ids
Every request gets two ids, both returned as response headers:
| Header | Source | |
|---|---|---|
$server->getRequestId() |
X-Request-Id |
Always generated by the server (UUID v4), never taken from the client |
$server->getCorrelationId() |
X-Correlation-ID |
The trace id of an incoming traceparent (W3C Trace Context), else a valid X-Correlation-ID or X-Request-Id of the caller, else the request id |
Incoming ids are client supplied: values with other characters than A-Z a-z 0-9 . _ : - or longer than 128 characters are ignored.
Add both ids to log entries and pass the correlation id on to calls a request makes (within your own services).
Response headers
JSON responses are data and are not HTML escaped, clients encode values where they show them. Every response carries:
X-Content-Type-Options: nosniff,Cache-Control: no-store,Content-Security-Policy: default-src 'none'; frame-ancestors 'none'Strict-Transport-Securityover HTTPSX-Request-Id,X-Correlation-ID
A route that renders HTML sends its own Content-Security-Policy and Cache-Control. The format follows the Accept header: XML when application/xml is preferred, JSON otherwise (a browser navigation, which lists text/html, gets JSON). #[ResponseFormat("json")] fixes the format of a route, e.g. for documents a standard defines as JSON.
Caching Routes
The route cache is built from the loaded controllers: set CLI_SCAN_FOLDERS (e.g. src/Controllers) so they are found. When no routes are found the cache is not written and an error names the cause, instead of every request answering 404.
Routes paths are cached in the cache folder, you can use the bin/api binary to cache routes. When there is no routes file, a cache will be created upon first use.
./bin/api cache routes -(v)erbose (--autoload <file>)
Enable APCU in your PHP build for faster route resolving. Build Docker images with the following command:
RUN pecl install apcu && docker-php-ext-enable apcu
Contributions
Contributions are welcome!
Please open an issue or submit a pull request following our contribution guidelines.