adil-jaafar / picophp
Ultra-léger, conçu pour aller à l'essentiel.
Installs: 15
Dependents: 1
Suggesters: 0
Security: 0
Stars: 1
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/adil-jaafar/picophp
README
picoPHP is a minimalistic yet powerful PHP framework designed for rapid development and ease of use. It leverages file-based routing, dependency injection, and middleware to provide a clean and organized structure for your web applications.
Key Features
- File-Based Routing: Define your routes simply by creating
routes.phpfiles within your application's directory structure. - Dependency Injection: Automatically inject services (like Request, Response, Env, DB) into your route handlers for easy access and testing.
- Path Parameters: Easily capture dynamic path segments as parameters within your routes.
- Middleware: Implement reusable logic that can be applied before and after route handlers, allowing you to easily manage authentication, authorization, data validation, and more.
- HTTP Method Handling: Easily define handlers for different HTTP methods (GET, POST, PUT, DELETE, etc.)
Getting Started
-
Installation: Use Composer to install picoPHP.
composer create-project adil-jaafar/picophp-template your-app-name
-
Directory Structure: Organize your application code within the
appdirectory.app/ ├── foo/ │ ├── bar/ │ │ └── routes.php # Defines routes for /foo/bar │ └── routes.php # Defines routes for /foo └── routes.php # Defines routes for the root (/) -
Routing with
routes.php: Createroutes.phpfiles to define your routes.<?php // app/foo/bar/routes.php $get = function(Request $request, Response $response) { $data = ['message' => 'Hello from /foo/bar']; return $response(200)->json($data); }; $post = function(Request $request, Response $response) { $body = $request->body(); // Process the POST data return $response(201)->json(['message' => 'Resource created', 'data' => $body]); };
This example defines a
GETandPOSTroute for/foo/bar. -
Accessing Services: picoPHP automatically injects the required services into your route handlers.
<?php // app/routes.php $get = function(Request $request, Response $response, Env $env, DB $db) { $appName = $env('APP_NAME', 'My App'); // Access environment variables $users = $db->fetchAll('SELECT * FROM users'); // Access the database return $response(200)->json(['app_name' => $appName, 'users' => $users]); };
-
Path Parameters: Use
Pathservice to access route parameters defined with square brackets in the directory structure.<?php // app/users/[id]/edit/routes.php $get = function(Path $path, Response $response) { $user_id = $path['id']; // Access the "id" parameter from the URL // Fetch user data based on $user_id // ... return $response(200)->json(['user_id' => $user_id, /* ... */]); }; // app/photo/[...chemin]/routes.php $get = function(Path $path, Response $response) { $photo_path = $path['chemin']; // Access the "chemin" parameter from the URL which can contain multiple segments // Ex: /photo/path/to/my/image.jpg // $photo_path will be equal to "path/to/my/image.jpg" // Serve the image at $photo_path // ... return $response(200); // Or any other response };
/users/123/editwill map to the function inapp/users/[id]/edit/routes.phpand the parameter 'id' will equal123./photo/path/to/my/image.jpgwill map to the function inapp/photo/[...chemin]/routes.phpand the parameter 'chemin' will equalpath/to/my/image.jpg.
-
Directory Naming Convention Folders enclosed in parentheses
()are intended for structural organization, e.g.,app/users/(admin)/edit/[user_id]. They are used to map paths like/users/edit/123to the route structure, whereuser_idcaptures the dynamic parameter. -
Middleware: Add middleware to
middleware.phpfiles in any directory within your application. Middleware allows you to execute code before and after route handlers.<?php // app/middleware.php $before = [ function(Request $request, Response $response, Env $env) { // Check authentication before allowing access $apiKey = $request->header('X-API-Key'); if ($apiKey !== $env('API_KEY')) { return $response(401)->json(['error' => 'Unauthorized']); } return true; // Continue to the route handler (if this returns nothing or is ommited) } ]; // app/foo/middleware.php $before = [ function(Request $request, Response $response) { // Log something error_log('Before foo'); return true; } ]; $after = [ function(Request $request, Response $response) { $response->header('X-Powered-By', 'PicoPHP'); return true; } ];
$before: An array of functions to execute before the route handler.- If any
$beforemiddleware function returns a value (other thantrueornull), that value is considered the response, and the route handler is not executed. - Returning
true(or nothing at all) from a$beforemiddleware function allows the request to proceed to the route handler (and to other$beforemiddleware further down in the application's folder structure) - If a
$beforemiddleware returns aResponseobject, processing stops, and the framework immediately returns this response. This is ideal for things like auth checks.
- If any
$after: An array of functions to execute after the route handler.$aftermiddleware run in the reverse order from the$beforemiddleware.
Middleware Execution Order:
$beforemiddleware functions are executed from the root directory down to the directory containing theroutes.phpfile. If abeforereturns a value other than true, processing stops.- The route handler function in
routes.phpis executed. $aftermiddleware functions are executed from the directory containing theroutes.phpfile up to the root directory.
Example: Authentication Middleware
Create a middleware.php file in your app directory to implement global authentication.
<?php // app/middleware.php $before = [ function(Request $request, Response $response) { if (!isAuthenticated($request)) { return $response(401)->json(['error' => 'Unauthorized']); } } ]; function isAuthenticated(Request $request): bool { //TODO replace by a real auth check $token = $request->header("authorization"); return $token === "Bearer mysecrettoken"; }