From 6184d28dda8c5890b9bd5cf981ccf4d28791058f Mon Sep 17 00:00:00 2001 From: Sky Johnson Date: Thu, 11 Sep 2025 08:42:40 -0500 Subject: [PATCH] add lots of procies to Context, add documentation and examples --- Context.php | 192 ++++++++++++++ EXAMPLES.md | 722 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 200 ++++++++++++++- 3 files changed, 1112 insertions(+), 2 deletions(-) create mode 100644 EXAMPLES.md diff --git a/Context.php b/Context.php index 9246c43..a1634ad 100644 --- a/Context.php +++ b/Context.php @@ -127,4 +127,196 @@ class Context return $this->validate($data, $rules, $messages); } + + /** + * header returns the value of a request header + */ + public function header(string $name): ?string + { + return $this->request->header($name); + } + + /** + * input returns input value from any source (route, query, post, json) + */ + public function input(string $name, mixed $default = null): mixed + { + return $this->request->input($name, $default); + } + + /** + * param returns a parameter from route params, query params, or post data + */ + public function param(string $name): mixed + { + return $this->request->param($name); + } + + /** + * all returns all input data merged from all sources + */ + public function all(): array + { + return $this->request->all(); + } + + /** + * only returns only specified keys from input + */ + public function only(array $keys): array + { + return $this->request->only($keys); + } + + /** + * except returns all input except specified keys + */ + public function except(array $keys): array + { + return $this->request->except($keys); + } + + /** + * has checks if input key exists + */ + public function has(string $key): bool + { + return $this->request->has($key); + } + + /** + * cookie returns the value of a request cookie + */ + public function cookie(string $name): ?string + { + return $this->request->cookie($name); + } + + /** + * expectsJson checks if request expects JSON response + */ + public function expectsJson(): bool + { + return $this->request->expectsJson(); + } + + /** + * isAjax checks if request is AJAX + */ + public function isAjax(): bool + { + return $this->request->isAjax(); + } + + /** + * ip returns the client IP address + */ + public function ip(): string + { + return $this->request->ip(); + } + + /** + * userAgent returns the user agent string + */ + public function userAgent(): string + { + return $this->request->userAgent(); + } + + /** + * referer returns the referer URL + */ + public function referer(): ?string + { + return $this->request->referer(); + } + + /** + * isSecure checks if request is over HTTPS + */ + public function isSecure(): bool + { + return $this->request->isSecure(); + } + + /** + * url returns the full URL of the request + */ + public function url(): string + { + return $this->request->url(); + } + + /** + * fullUrl returns the URL with query string + */ + public function fullUrl(): string + { + return $this->request->fullUrl(); + } + + /** + * is checks if the request path matches a pattern + */ + public function is(string $pattern): bool + { + return $this->request->is($pattern); + } + + /** + * contentType returns the request content type without charset + */ + public function contentType(): string + { + return $this->request->contentType(); + } + + /** + * status sets the HTTP status code for the response + */ + public function status(int $code): Response + { + return $this->response->status($code); + } + + /** + * setHeader sets a header for the response + */ + public function setHeader(string $name, string $value): Response + { + return $this->response->header($name, $value); + } + + /** + * setCookie sets a cookie with the given name, value, and options + */ + public function setCookie(string $name, string $value, array $options = []): Response + { + return $this->response->cookie($name, $value, $options); + } + + /** + * write adds content to the response body + */ + public function write(string $content): Response + { + return $this->response->write($content); + } + + /** + * end ends the response with optional content + */ + public function end(string $content = ''): void + { + $this->response->end($content); + } + + /** + * send sends the response to the client + */ + public function send(): void + { + $this->response->send(); + } } diff --git a/EXAMPLES.md b/EXAMPLES.md new file mode 100644 index 0000000..52b1644 --- /dev/null +++ b/EXAMPLES.md @@ -0,0 +1,722 @@ +# Web Framework Examples + +This file contains practical examples demonstrating how to use the Web framework. + +## Quick Start + +```php +get('/', function(Context $context) { + return 'Hello World!'; +}); + +$app->get('/users/:id', function(Context $context, $id) { + return ['user_id' => $id, 'name' => 'John Doe']; +}); + +$app->run(); +?> +``` + +## Web Application Examples + +### Basic Setup + +```php +// Create application with debug mode +$app = new Web(debug: true); + +// Add global middleware +$app->use(function(Context $context, callable $next) { + // Pre-processing + $next(); + // Post-processing +}); + +// Define routes +$app->get('/path', $handler); +$app->post('/path', $handler); +$app->put('/path', $handler); +$app->patch('/path', $handler); +$app->delete('/path', $handler); +$app->head('/path', $handler); + +// Route groups +$app->group('/api', function(Web $app) { + $app->get('/users', $usersHandler); + $app->post('/users', $createUserHandler); +}); + +// Custom error handlers +$app->setErrorHandler(404, function(Context $context) { + $context->json(['error' => 'Custom 404'], 404); +}); + +$app->setDefaultErrorHandler(function(Context $context, int $status, string $message, ?Exception $e) { + $context->json(['error' => $message, 'status' => $status], $status); +}); + +// Start the application +$app->run(); +``` + +## Router Examples + +```php +$router = new Router(); + +// Add routes with dynamic parameters +$router->get('/posts/:id', $handler); +$router->post('/users/:userId/posts/:postId', $handler); + +// Perform lookup +$result = $router->lookup('GET', '/posts/123'); +// Returns: ['code' => 200, 'handler' => $handler, 'params' => ['123']] + +// Route patterns +'/users/:id' // matches /users/123, /users/abc +'/posts/:slug/edit' // matches /posts/my-post/edit +'/' // matches root path +``` + +## Context Examples + +### Request Helpers + +```php +// Get input from any source (route params, query, POST, JSON) +$name = $context->input('name', 'default'); +$email = $context->input('email'); + +// Get specific parameter types +$id = $context->param('id'); // route/query/post params +$all = $context->all(); // all input data +$data = $context->only(['name', 'email']); // specific keys only +$data = $context->except(['password']); // all except specified keys + +// Check if input exists +if ($context->has('email')) { + // handle email +} + +// Request headers and cookies +$auth = $context->header('authorization'); +$token = $context->cookie('session_token'); + +// Request information +$ip = $context->ip(); +$userAgent = $context->userAgent(); +$referer = $context->referer(); +$contentType = $context->contentType(); + +// Request checks +if ($context->expectsJson()) { + // return JSON response +} + +if ($context->isAjax()) { + // handle AJAX request +} + +if ($context->isSecure()) { + // HTTPS request +} + +// URL helpers +$url = $context->url(); // full URL +$fullUrl = $context->fullUrl(); // URL with query string + +// Path matching +if ($context->is('api/*')) { + // matches API routes +} +``` + +### Response Helpers + +```php +// Set status and headers +$context->status(201); +$context->setHeader('X-Custom', 'value'); +$context->setCookie('name', 'value', ['expires' => time() + 3600]); + +// Response content +$context->json(['message' => 'Success']); // JSON response +$context->text('Hello World'); // Plain text +$context->html('

Hello

'); // HTML +$context->redirect('/login'); // Redirect +$context->error(404, 'Not Found'); // Error response + +// Manual response building +$context->write('Some content'); +$context->write(' more content'); +$context->send(); // Send response + +// Or end with content +$context->end('Final content'); +``` + +### State Management + +```php +// Store and retrieve context state +$context->set('user', $user); +$user = $context->get('user'); +``` + +### Validation + +```php +// Validate request data +$validator = $context->validateRequest([ + 'email' => 'required|email', + 'name' => 'required|string|min:2' +]); + +// Validate any data +$validator = $context->validate($data, [ + 'field' => 'required|string' +], ['field.required' => 'Custom error message']); +``` + +## Request Examples + +```php +$request = new Request(); + +// Basic properties +$request->method; // GET, POST, etc. +$request->uri; // /path?query=value +$request->path; // /path +$request->query; // query=value +$request->body; // raw request body + +// Parsed data +$request->queryParams; // parsed query parameters +$request->postData; // parsed POST data +$request->params; // route parameters (set by router) + +// Input methods +$value = $request->input('key', 'default'); // from any source +$value = $request->param('key'); // route/query/post only +$all = $request->all(); // all input merged +$subset = $request->only(['key1', 'key2']); +$subset = $request->except(['password']); +$exists = $request->has('key'); + +// Headers and cookies +$auth = $request->header('authorization'); +$type = $request->contentType(); +$cookie = $request->cookie('session'); + +// JSON handling +$data = $request->json(); // decode JSON body + +// Request info +$ip = $request->ip(); +$agent = $request->userAgent(); +$referer = $request->referer(); +$secure = $request->isSecure(); +$ajax = $request->isAjax(); +$expectsJson = $request->expectsJson(); + +// URL info +$url = $request->url(); +$fullUrl = $request->fullUrl(); +$matches = $request->is('admin/*'); // path matching +``` + +## Response Examples + +```php +$response = new Response(); + +// Set status and headers +$response->status(201) + ->header('Content-Type', 'application/json') + ->header('X-Custom', 'value'); + +// Content methods +$response->json($data, 201); // JSON with status +$response->text('Hello', 200); // Plain text +$response->html('

Hi

', 200); // HTML +$response->redirect('/login', 302); // Redirect + +// Cookies +$response->cookie('name', 'value', [ + 'expires' => time() + 3600, + 'path' => '/', + 'secure' => true, + 'httponly' => true, + 'samesite' => 'Strict' +]); + +// Manual building +$response->write('Part 1'); +$response->write('Part 2'); +$response->send(); // Send to client + +// Or end immediately +$response->end('Final content'); +``` + +## Session Examples + +```php +$session = new Session(); +$session->start(); + +// Basic session data +$session->set('key', 'value'); +$value = $session->get('key', 'default'); +$exists = $session->has('key'); +$session->remove('key'); + +// Flash messages (available only for next request) +$session->flash('success', 'Data saved!'); +$message = $session->getFlash('success'); +$hasMessage = $session->hasFlash('error'); + +// CSRF protection +$token = $session->csrfToken(); +$valid = $session->validateCsrf($userToken); + +// Session management +$session->regenerate(); // Regenerate session ID +$session->destroy(); // Destroy session completely +$session->clear(); // Clear data but keep session active +$all = $session->all(); // Get all session data +``` + +## Validation Examples + +```php +$validator = new Validator(); + +// Validate data +$isValid = $validator->validate($data, [ + 'email' => 'required|email', + 'password' => 'required|min:8', + 'age' => 'integer|between:18,120', + 'tags' => 'array', + 'website' => 'url', + 'role' => 'in:admin,user,moderator' +], [ + 'email.required' => 'Email is mandatory', + 'password.min' => 'Password must be at least 8 characters' +]); + +// Check results +if ($validator->failed()) { + $errors = $validator->errors(); + $firstError = $validator->firstError(); + $fieldError = $validator->firstError('email'); +} + +// Custom validation rules +Validator::extend('custom', function($value, $parameters, $data) { + return $value === 'custom_value'; +}); +``` + +## Authentication Examples + +```php +$auth = new Auth($session, [ + 'cookie_name' => 'remember_token', + 'cookie_lifetime' => 2592000, // 30 days + 'cookie_secure' => true +]); + +// Authentication +$auth->login($userData, $remember = false); +$auth->loginUser($userObject, $remember = false); +$auth->logout(); + +// User checks +$isAuthenticated = $auth->check(); +$isGuest = $auth->guest(); +$user = $auth->user(); +$userId = $auth->id(); + +// Password handling +$hash = $auth->hashPassword('password'); +$valid = $auth->verifyPassword('password', $hash); + +// Manual user data management +$auth->setUserData($userData); +$auth->clear(); // Clear all auth data +``` + +## User Model Examples + +```php +$user = new User([ + 'id' => 1, + 'username' => 'john', + 'email' => 'john@example.com', + 'role' => 'admin' +]); + +// Properties +$user->id; +$user->username; +$user->email; +$user->role; + +// Methods +$identifier = $user->getIdentifier(); // email or username +$id = $user->getId(); +$array = $user->toArray(); // with all data +$safe = $user->toSafeArray(); // without sensitive data +``` + +## Auth Middleware Examples + +```php +$authMiddleware = new AuthMiddleware($auth); + +// Require authentication +$app->use($authMiddleware->requireAuth()); + +// Require guest (not authenticated) +$app->use($authMiddleware->requireGuest()); + +// Optional authentication +$app->use($authMiddleware->optional()); + +// Role-based access +$app->use($authMiddleware->requireRole('admin')); +$app->use($authMiddleware->requireRole(['admin', 'moderator'])); + +// Rate limiting +$app->use($authMiddleware->rateLimit(maxAttempts: 60, decayMinutes: 1)); + +// CSRF protection +$app->use($authMiddleware->verifyCsrf()); + +// Remember token handling +$app->use($authMiddleware->remember()); +``` + +## Error Handling Examples + +```php +$errorHandler = new ErrorHandler(debug: true); + +// Register custom error handlers +$errorHandler->register(404, function(Context $context, int $status, string $message) { + $context->json(['error' => 'Custom not found'], 404); +}); + +$errorHandler->setDefaultHandler(function(Context $context, int $status, string $message, ?Exception $e) { + $context->json(['error' => $message, 'code' => $status], $status); +}); + +// Handle errors manually +$errorHandler->handle($context, 500, 'Server Error', $exception); +$errorHandler->handleException($context, $exception); + +// Custom exceptions +throw new HttpException(422, 'Unprocessable Entity'); +throw new ValidationException($validator->errors(), 'Validation failed'); +``` + +## Middleware Examples + +```php +// Basic middleware +$app->use(function(Context $context, callable $next) { + // Pre-processing + $start = microtime(true); + + $next(); // Call next middleware/handler + + // Post-processing + $duration = microtime(true) - $start; + $context->setHeader('X-Response-Time', $duration . 'ms'); +}); + +// Conditional middleware +$app->use(function(Context $context, callable $next) { + if ($context->is('api/*')) { + $context->setHeader('Content-Type', 'application/json'); + } + $next(); +}); + +// Logging middleware +$app->use(function(Context $context, callable $next) { + $method = $context->request->method; + $path = $context->request->path; + $ip = $context->ip(); + + error_log("[$method] $path from $ip"); + $next(); +}); + +// CORS middleware +$app->use(function(Context $context, callable $next) { + $context->setHeader('Access-Control-Allow-Origin', '*'); + $context->setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); + $context->setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); + + if ($context->request->method === 'OPTIONS') { + $context->status(200)->send(); + return; + } + + $next(); +}); +``` + +## Route Handler Examples + +```php +// Simple handler +$app->get('/hello', function(Context $context) { + return 'Hello World!'; +}); + +// Handler with parameters +$app->get('/users/:id/posts/:slug', function(Context $context, $userId, $slug) { + return [ + 'user_id' => $userId, + 'post_slug' => $slug, + 'data' => $context->all() + ]; +}); + +// Handler return types +$app->get('/json', fn($context) => ['key' => 'value']); // Auto JSON +$app->get('/text', fn($context) => 'Plain text'); // Auto text +$app->get('/response', fn($context) => $context->json([])); // Manual response + +// Complex handler with validation +$app->post('/users', function(Context $context) { + $context->validateRequest([ + 'name' => 'required|string|min:2', + 'email' => 'required|email', + 'age' => 'integer|min:18' + ]); + + $userData = $context->only(['name', 'email', 'age']); + + // Save user logic here + $userId = saveUser($userData); + + return [ + 'message' => 'User created successfully', + 'user_id' => $userId + ]; +}); + +// File upload handler +$app->post('/upload', function(Context $context) { + if (!isset($_FILES['file'])) { + $context->error(400, 'No file uploaded'); + return; + } + + $file = $_FILES['file']; + + if ($file['error'] !== UPLOAD_ERR_OK) { + $context->error(400, 'Upload failed'); + return; + } + + // Handle file upload logic + $filename = handleFileUpload($file); + + return ['filename' => $filename]; +}); +``` + +## Complete Application Example + +```php +context->session); +$authMiddleware = new AuthMiddleware($auth); + +// Global middleware +$app->use(function(Context $context, callable $next) { + $context->setHeader('X-Framework', 'Web'); + $next(); +}); + +// Auth routes +$app->post('/login', function(Context $context) use ($auth) { + $context->validateRequest([ + 'email' => 'required|email', + 'password' => 'required|min:6' + ]); + + $email = $context->input('email'); + $password = $context->input('password'); + + // Verify credentials externally, then login + if (verifyCredentials($email, $password)) { + $userData = getUserData($email); + $auth->login($userData, $context->input('remember')); + return ['message' => 'Logged in successfully']; + } + + $context->error(401, 'Invalid credentials'); +}); + +$app->post('/logout', function(Context $context) use ($auth) { + $auth->logout(); + return ['message' => 'Logged out']; +}); + +// Protected routes +$app->group('/api', function(Web $app) use ($authMiddleware) { + $app->use($authMiddleware->requireAuth()); + $app->use($authMiddleware->rateLimit(100, 1)); + + $app->get('/profile', function(Context $context) { + return $context->get('user')->toSafeArray(); + }); + + $app->put('/profile', function(Context $context) { + $context->validateRequest([ + 'name' => 'required|string|min:2', + 'email' => 'required|email' + ]); + + // Update profile logic here + return ['message' => 'Profile updated']; + }); + + $app->get('/posts', function(Context $context) { + $page = $context->input('page', 1); + $limit = $context->input('limit', 10); + + // Get posts with pagination + $posts = getPosts($page, $limit); + + return [ + 'posts' => $posts, + 'pagination' => [ + 'page' => $page, + 'limit' => $limit + ] + ]; + }); + + $app->post('/posts', function(Context $context) { + $context->validateRequest([ + 'title' => 'required|string|min:5', + 'content' => 'required|string|min:10', + 'tags' => 'array' + ]); + + $postData = $context->only(['title', 'content', 'tags']); + $postData['user_id'] = $context->get('user')->id; + + $postId = createPost($postData); + + return [ + 'message' => 'Post created successfully', + 'post_id' => $postId + ]; + }); +}); + +// Admin routes +$app->group('/admin', function(Web $app) use ($authMiddleware) { + $app->use($authMiddleware->requireRole('admin')); + + $app->get('/users', function(Context $context) { + return ['users' => getAllUsers()]; + }); + + $app->delete('/users/:id', function(Context $context, $userId) { + deleteUser($userId); + return ['message' => 'User deleted successfully']; + }); + + $app->get('/stats', function(Context $context) { + return [ + 'total_users' => getUserCount(), + 'total_posts' => getPostCount(), + 'active_sessions' => getActiveSessionCount() + ]; + }); +}); + +// Public API routes +$app->group('/public', function(Web $app) { + $app->get('/posts', function(Context $context) { + $posts = getPublicPosts(); + return ['posts' => $posts]; + }); + + $app->get('/posts/:id', function(Context $context, $postId) { + $post = getPublicPost($postId); + if (!$post) { + $context->error(404, 'Post not found'); + return; + } + return ['post' => $post]; + }); +}); + +// Error handlers +$app->setErrorHandler(404, function(Context $context) { + if ($context->expectsJson()) { + $context->json(['error' => 'Endpoint not found'], 404); + } else { + $context->html('

Page Not Found

', 404); + } +}); + +$app->setErrorHandler(429, function(Context $context) { + $context->json([ + 'error' => 'Rate limit exceeded', + 'message' => 'Please slow down your requests' + ], 429); +}); + +$app->run(); +?> +``` + +## Testing Examples + +```php +// Simple test setup +function testRoute($method, $path, $data = []) { + $_SERVER['REQUEST_METHOD'] = $method; + $_SERVER['REQUEST_URI'] = $path; + + if ($method === 'POST' && $data) { + $_POST = $data; + } + + $app = new Web(); + // Setup your routes... + + ob_start(); + $app->run(); + $output = ob_get_clean(); + + return $output; +} + +// Test examples +$response = testRoute('GET', '/api/users'); +$response = testRoute('POST', '/api/users', ['name' => 'John', 'email' => 'john@example.com']); +``` \ No newline at end of file diff --git a/README.md b/README.md index dfcac44..7783e6b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,199 @@ -# Web +# Web Framework -Web is a crazy-simple PHP web framework, built to be simple and performant. It uses my hyper-optimized tree-based router at its core, adding only minimal overhead for convenience and flexibility. The Web framework itself adds middleware support, grouping, etc. +Web is a lightweight, high-performance PHP web framework built around a hyper-optimized tree-based router. It provides essential web application features with minimal overhead, including routing, middleware, sessions, validation, authentication, and error handling. + +## Quick Start + +```php +get('/', function(Context $context) { + return 'Hello World!'; +}); + +$app->get('/users/:id', function(Context $context, $id) { + return ['user_id' => $id, 'name' => 'John Doe']; +}); + +$app->run(); +?> +``` + +See [EXAMPLES.md](EXAMPLES.md) for comprehensive examples and usage patterns. + +## Core Components + +### Web Application +The main application class that handles routing, middleware, and request processing. +- Route registration (`get()`, `post()`, `put()`, `patch()`, `delete()`, `head()`) +- Middleware support (`use()`) +- Route grouping (`group()`) +- Custom error handling (`setErrorHandler()`, `setDefaultErrorHandler()`) + +### Router +High-performance tree-based router with dynamic parameter support. +- Optimized route lookup algorithm +- Dynamic segments with `:parameter` syntax +- Returns status codes (200, 404, 405) with matched handlers and parameters + +### Context +Central request/response wrapper with helper methods to reduce chaining. +- Request helpers: `input()`, `param()`, `all()`, `only()`, `except()`, `has()` +- Response helpers: `json()`, `text()`, `html()`, `redirect()`, `error()` +- Request info: `ip()`, `userAgent()`, `header()`, `cookie()`, `expectsJson()` +- State management: `set()`, `get()` +- Validation: `validate()`, `validateRequest()` + +### Request +Comprehensive HTTP request handling. +- Input parsing from query, POST, JSON, and route parameters +- Header and cookie access +- Content type detection +- URL and security helpers + +### Response +HTTP response building with method chaining. +- Status codes and headers +- Content types: JSON, HTML, text, redirects +- Cookie management +- Manual response building + +### Session +Session management with security features. +- Basic session data storage +- Flash messages for one-time notifications +- CSRF token generation and validation +- Session lifecycle management + +### Validator +Input validation with 20+ built-in rules. +- Chainable validation rules (`required|email|min:6`) +- Custom error messages +- Extensible with custom rules +- Dot notation support for nested data + +### Authentication +User authentication with session and remember token support. +- Login/logout functionality +- Password hashing and verification +- Remember token management +- External credential verification support + +### Auth Middleware +Authentication and authorization middleware. +- Authentication requirements (`requireAuth()`, `requireGuest()`) +- Role-based access control (`requireRole()`) +- Rate limiting (`rateLimit()`) +- CSRF protection (`verifyCsrf()`) + +### Error Handling +Comprehensive error and exception handling. +- Custom error handlers for specific status codes +- Debug mode with stack traces +- Automatic JSON/HTML response formatting +- Built-in error pages + +## API Reference + +### Web Class +```php +new Web(bool $debug = false) +use(callable $middleware): self +get|post|put|patch|delete|head(string $route, callable $handler): self +group(string $prefix, callable $callback): self +setErrorHandler(int $status, callable $handler): self +setDefaultErrorHandler(callable $handler): self +run(): void +``` + +### Context Class +```php +// Request helpers +input(string $name, mixed $default = null): mixed +param(string $name): mixed +all(): array +only(array $keys): array +except(array $keys): array +has(string $key): bool +header(string $name): ?string +cookie(string $name): ?string +ip(): string +userAgent(): string +expectsJson(): bool +isAjax(): bool +isSecure(): bool + +// Response helpers +json(mixed $data, int $status = 200): void +text(string $text, int $status = 200): void +html(string $html, int $status = 200): void +redirect(string $url, int $status = 302): void +error(int $status, string $message = ''): void +status(int $code): Response +setHeader(string $name, string $value): Response +setCookie(string $name, string $value, array $options = []): Response + +// State management +set(string $key, mixed $value): void +get(string $key): mixed + +// Validation +validate(array $data, array $rules, array $messages = []): Validator +validateRequest(array $rules, array $messages = []): Validator +``` + +### Validator Rules +`required`, `email`, `url`, `alpha`, `alphaNum`, `numeric`, `integer`, `float`, `boolean`, `array`, `json`, `date`, `min:n`, `max:n`, `between:min,max`, `length:n`, `in:a,b,c`, `notIn:a,b,c`, `regex:/pattern/`, `confirmed`, `unique:table,column`, `exists:table,column` + +### Auth Class +```php +new Auth(Session $session, array $config = []) +login(array $userData, bool $remember = false): void +logout(): void +check(): bool +guest(): bool +user(): ?User +id(): int|string|null +hashPassword(string $password): string +verifyPassword(string $password, string $hash): bool +``` + +### AuthMiddleware Methods +```php +requireAuth(): callable +requireGuest(): callable +optional(): callable +requireRole(string|array $roles): callable +rateLimit(int $maxAttempts = 60, int $decayMinutes = 1): callable +verifyCsrf(): callable +``` + +## Features + +- **High Performance**: Tree-based router with O(1) lookup complexity +- **Minimal Overhead**: Lightweight design with essential features only +- **Method Chaining**: Fluent API for response building +- **Middleware Support**: Pre/post request processing +- **Route Groups**: Organize routes with shared prefixes and middleware +- **Input Validation**: Comprehensive validation with built-in rules +- **Authentication**: Session-based auth with remember tokens +- **Error Handling**: Custom error pages with debug support +- **CSRF Protection**: Built-in CSRF token generation and validation +- **Flash Messages**: One-time notifications between requests +- **Rate Limiting**: Configurable rate limiting per user/IP +- **Content Negotiation**: Automatic JSON/HTML response selection + +## Documentation + +- **[EXAMPLES.md](EXAMPLES.md)** - Comprehensive examples and usage patterns +- **API Reference** - Complete method documentation (above) +- **Source Code** - Well-documented PHP classes + +## Requirements + +- PHP 8.1+ (uses enums and modern syntax) +- No external dependencies +- Works with any PHP web server \ No newline at end of file