schentrup-software / php-api
A basic api framework for PHP. It uses classes for request and responses to make a self documenting API.
Fund package maintenance!
joeySchentrup
Requires
- php: >=8.1
- pmjones/auto-route: ^2.0
- sapien/sapien: ^1.1
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.9
- phan/phan: ^5.4
- phpunit/phpunit: 8.*
This package is auto-updated.
Last update: 2025-04-21 00:33:47 UTC
README
A basic api framework for PHP. It uses classes for request and responses to make a self documenting API. It uses pmjones/AutoRoute for routing and sapienphp/sapien for request and response objects.
Features
- Convention-Based Routing: Automatically maps URLs to controller classes based on directory structure and naming conventions
- Strongly Typed Requests/Responses: Type-safe request and response objects with automatic parameter parsing
- Auto-Generated Swagger Documentation: API documentation automatically generated from your code and PHP attributes
- Middleware Support: Add request/response middleware for cross-cutting concerns like authentication and logging
- Content Negotiation: Support for different content types (JSON, Form data, etc.)
- Input Validation: Automatic validation and type conversion of request parameters
- Path Variables: Support for dynamic path segments in routes
- Error Handling: Customizable error responses for various error conditions
- Attribute-Based Metadata: Use PHP 8 attributes for documentation and parameter configuration
- Parameter Sources: Get input from different sources (query parameters, JSON body, cookies, headers)
Installation
composer require schentrup-software/php-api
Basic Usage
- Create a Router
<?php // index.php require_once __DIR__ . '/vendor/autoload.php'; use PhpApi\Router; use PhpApi\Model\RouterOptions; use PhpApi\Model\SwaggerOptions; $router = new Router( new RouterOptions( namespace: 'YourApp\\Routes', directory: __DIR__ . '/src/Routes', ), new SwaggerOptions( title: "Your API Documentation", apiVersion: "1.0.0", ) ); $router->route()->send();
- Create a Simple Controller
<?php // src/Routes/Get.php namespace YourApp\Routes; use PhpApi\Model\Response\AbstractJsonResponse; use PhpApi\Swagger\Attribute\SwaggerTag; use PhpApi\Swagger\Attribute\SwaggerDescription; #[SwaggerTag(name: 'Hello', description: 'Hello world example')] class Get { #[SwaggerDescription('Returns a hello world message')] public function execute(): HelloResponse { return new HelloResponse(); } } class HelloResponse extends AbstractJsonResponse { public const ResponseCode = 200; public function __construct( public string $message = 'Hello, World!', public string $timestamp = '', ) { $this->timestamp = date('Y-m-d H:i:s'); } }
Request Parameters
PHP-API supports multiple parameter sources:
Query Parameters
<?php class GetUsers extends AbstractRequest { public function __construct( #[QueryParam] public int $page = 1, #[QueryParam] public int $limit = 10 ) { } }
JSON Body Parameters
<?php class CreateUserRequest extends AbstractRequest { public function __construct( #[JsonRequestParam] public string $name, ) { } }
or
<?php #[JsonRequestParam] class CreateUserRequest extends AbstractRequest { public function __construct( public string $name, ) { } }
Header Parameters
<?php class AuthenticatedRequest extends AbstractRequest { public function __construct( #[HeaderRequestParam(name: 'Authorization')] public string $token ) { } }
Cookie Parameters
<?php class SessionRequest extends AbstractRequest { public function __construct( #[CookieRequestParam(name: 'session_id')] public ?string $sessionId = null ) { } }
Middleware
Request Middleware
<?php class AuthenticationMiddleware implements IRequestMiddleware { public function handleRequest(AbstractRequest $request): AbstractRequest { if ($request instanceof AuthenticatedRequest) { // Validate token if (!$this->validateToken($request->token)) { throw new Exception('Invalid token'); } } return $request; } private function validateToken(string $token): bool { // Token validation logic return true; } }
Response Middleware
<?php class TimestampMiddleware implements IResponseMiddleware { public function handleResponse(AbstractResponse $response): AbstractResponse { if (property_exists($response, 'timestamp') && !isset($response->timestamp)) { $response->timestamp = time(); } return $response; } }
Adding Middleware
<?php $router = new Router($options); $router->addMiddleware(new AuthenticationMiddleware()); $router->addMiddleware(new TimestampMiddleware());
Error Handling
<?php // Custom 404 page $router->handleNotFound('/error/404'); // Custom 404 response $response = new Response(); $response->setCode(404); $response->setContent('{"error": "Resource not found"}'); $router->handleNotFound($response); // Custom handler with closure $router->handleNotFound(function(Request $req) { $response = new Response(); $response->setCode(404); $response->setContent("Could not find: " . $req->url->path); return $response; });
Swagger Documentation
PHP-API automatically generates Swagger/OpenAPI documentation from your code. Access the documentation at:
- /swagger - Swagger UI interface
- /swagger/json - Raw JSON OpenAPI definition
Use attributes to enhance the documentation:
<?php #[SwaggerTag(name: 'Users', description: 'User management endpoints')] class PostUser { #[SwaggerSummary('Create a new user')] #[SwaggerDescription('Creates a new user with the provided information')] public function execute(CreateUserRequest $request): UserResponse { // Implementation } }
Path Variables
Path variables are automatically mapped to method parameters:
<?php // Maps to /users/{id} class GetUsersId { public function execute($_, int $id): UserResponse { return new UserResponse($id); } }
More info on this can be found in the auto-router documentation: pmjones/auto-route.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.