Skip to main content

php-pure

Use this skill when building PHP applications without a framework — PSR standards, routing, middleware, database access, error handling, and security. This skill enforces: PSR-4 autoloading, PSR-7 request/response, PSR-15 middleware, PSR-11 container, PSR-3 logging. Requires PHP 8.1+. Do NOT use for: Laravel, Symfony, WordPress, or framework-specific PHP development.

Datos de origen

Repositorio
j4flmao/agent-skills
Última actividad en el origen
6 de septiembre de 2026 a las 13:45
Idioma detectado de SKILL.md
inglés
Estrellas
27
Forks
1

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Explorador de archivos
7 archivos

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
php-pure
description
Use this skill when building PHP applications without a framework — PSR standards, routing, middleware, database access, error handling, and security. This skill enforces: PSR-4 autoloading, PSR-7 request/response, PSR-15 middleware, PSR-11 container, PSR-3 logging. Requires PHP 8.1+. Do NOT use for: Laravel, Symfony, WordPress, or framework-specific PHP development.
version
1.0.0
author
j4flmao
license
MIT
compatibility
{"claude-code":true,"cursor":true,"codex":true,"windsurf":true}
tags
["backend","php","pure","phase-4"]
# PHP (Pure/Standard) ## Purpose Build PHP applications without a framework — PSR standards-based architecture, routing, middleware, database access, type-safe with PHP 8.x features, and security-first patterns. ## Agent Protocol ### Trigger User request includes: `pure PHP`, `PHP without framework`, `PHP PSR`, `PHP routing`, `PHP middleware`, `PHP DI`, `PHP database`, `PHP 8 attributes`, `PHP enum`. ### Input Context - PHP version (8.1+) - PSR implementations (PSR-7, PSR-15, PSR-11, PSR-3) - Database (PDO, Doctrine DBAL, MySQLi) - Container (PHP-DI, custom) ### Output Artifact Project structure, router class, middleware chain, controller, database repository. ### Response Format Produce artifact directly. No preamble, no postamble, no explanations. ### Completion Criteria - PSR-4 autoloading configured - PSR-7 request/response handling - PSR-15 middleware pipeline - PSR-11 container for DI - Route matching with attributes or configuration - PDO with prepared statements ### Max Response Length 4096 tokens ## Architecture Decision Trees ### Micro-framework vs Full Framework vs Pure PHP | Criterion | Pure PHP (PSR stack) | Micro-framework (Slim) | Full Framework (Laravel) | |-----------|---------------------|----------------------|--------------------------| | Control | Complete | High | Framework conventions | | Setup time | High | Low | Very low | | Performance | Best | Good | Moderate | | Learning curve | Steep | Low | Moderate | | Flexibility | Max | High | Constrained by conventions | Decision: Full control + performance → Pure PHP. Quick REST API → Slim/Fat-Free. Full features → Laravel/Symfony. ### PHP 8 Features for Clean Architecture | Feature | Use | Benefit | |---------|-----|---------| | Attributes | Route definitions, validation, middleware | Declarative metadata without annotations | | Enums | Status, roles, types | Type-safe constants | | Readonly properties | DTOs, value objects | Immutability by default | | Named arguments | Constructor DI | Self-documenting dependencies | | Match expression | Error mapping, event routing | Exhaustive pattern matching | | Union types | Multi-type returns | Type-safe polymorphic returns | | Constructor promotion | DTOs, services | Reduces boilerplate | ## Workflow ### Step 1: Project Structure ``` project/ public/ index.php # Entry point src/ Controllers/ UserController.php Middleware/ AuthMiddleware.php CorsMiddleware.php ErrorHandlerMiddleware.php Router/ Router.php Route.php Request/ Request.php # PSR-7 implementation Response/ Response.php Container/ Container.php # PSR-11 implementation Repository/ UserRepository.php Service/ UserService.php Exception/ NotFoundException.php ValidationException.php Enum/ UserRole.php config/ routes.php services.php composer.json ``` ### Step 2: Composer Setup and PSR-4 ```json { "name": "app/api", "require": { "php": ">=8.1", "psr/http-message": "^1.0", "psr/container": "^2.0", "psr/log": "^3.0" }, "autoload": { "psr-4": { "App\\": "src/" } } } ``` ### Step 3: Router with PHP 8 Attributes ```php <?php // src/Router/Route.php namespace App\Router; #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class Route { public function __construct( public readonly string $method, public readonly string $path, ) {} } // src/Router/Router.php namespace App\Router; use App\Exception\NotFoundException; use Psr\Container\ContainerInterface; use Psr\Http\Message\ServerRequestInterface; class Router { private array $routes = []; public function register(string $class): void { $reflection = new \ReflectionClass($class); foreach ($reflection->getMethods() as $method) { foreach ($method->getAttributes(Route::class) as $attribute) { $route = $attribute->newInstance(); $this->routes[] = [ 'method' => $route->method, 'path' => $route->path, 'class' => $class, 'handler' => $method->getName(), ]; } } } public function dispatch(ServerRequestInterface $request, ContainerInterface $container): mixed { $method = $request->getMethod(); $uri = $request->getUri()->getPath(); foreach ($this->routes as $route) { $params = $this->match($route['method'], $route['path'], $method, $uri); if ($params !== null) { $controller = $container->get($route['class']); return $controller->{$route['handler']}($request, ...$params); } } throw new NotFoundException('Route not found'); } private function match(string $routeMethod, string $routePath, string $requestMethod, string $requestUri): ?array { if ($routeMethod !== $requestMethod) return null; $pattern = preg_replace('/\{(\w+)\}/', '(?P<$1>[^/]+)', $routePath); $pattern = '#^' . $pattern . '$#'; if (preg_match($pattern, $requestUri, $matches)) { return array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY); } return null; } } // src/Enum/UserRole.php namespace App\Enum; enum UserRole: string { case Admin = 'admin'; case User = 'user'; case Moderator = 'moderator'; } // src/Controllers/UserController.php namespace App\Controllers; use App\Router\Route; use App\Service\UserService; use Psr\Http\Message\ServerRequestInterface; class UserController { public function __construct( private readonly UserService $userService, ) {} #[Route('GET', '/users')] public function list(ServerRequestInterface $request): array { $page = (int) ($request->getQueryParams()['page'] ?? 1); return $this->userService->paginate($page); } #[Route('GET', '/users/{id}')] public function getById(ServerRequestInterface $request, string $id): ?array { $user = $this->userService->findById($id); if (!$user) throw new NotFoundException('User not found'); return $user; } #[Route('POST', '/users')] public function create(ServerRequestInterface $request): array { $data = json_decode((string) $request->getBody(), true); return $this->userService->create($data); } } ``` ### Step 4: Middleware Pipeline (PSR-15) ```php <?php // src/Middleware/Pipeline.php namespace App\Middleware; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; class Pipeline implements RequestHandlerInterface { private array $middleware = []; private int $index = 0; public function __construct( private readonly RequestHandlerInterface $handler, ) {} public function add(MiddlewareInterface $middleware): void { $this->middleware[] = $middleware; } public function handle(ServerRequestInterface $request): ResponseInterface { if ($this->index < count($this->middleware)) { $middleware = $this->middleware[$this->index]; $this->index++; return $middleware->process($request, $this); } return $this->handler->handle($request); } } // src/Middleware/AuthMiddleware.php namespace App\Middleware; use Firebase\JWT\JWT; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; class AuthMiddleware implements MiddlewareInterface { public function __construct( private readonly string $jwtSecret, ) {} public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $header = $request->getHeaderLine('Authorization'); if (!str_starts_with($header, 'Bearer ')) { throw new UnauthorizedException('Missing token'); } try { $token = substr($header, 7); $payload = JWT::decode($token, new Key($this->jwtSecret, 'HS256')); $request = $request->withAttribute('user_id', $payload->sub); $request = $request->withAttribute('user_role', $payload->role); } catch (\Exception) { throw new UnauthorizedException('Invalid token'); } return $handler->handle($request); } } ``` ### Step 5: PDO Database Access ```php <?php // src/Repository/UserRepository.php namespace App\Repository; use App\Enum\UserRole; use PDO; class UserRepository { public function __construct( private readonly PDO $pdo, ) {} public function findById(string $id): ?array { $stmt = $this->pdo->prepare('SELECT id, name, email, role, is_active, created_at FROM users WHERE id = :id'); $stmt->execute([':id' => $id]); $user = $stmt->fetch(PDO::FETCH_ASSOC); return $user ?: null; } public function findByEmail(string $email): ?array { $stmt = $this->pdo->prepare('SELECT * FROM users WHERE email = :email'); $stmt->execute([':email' => $email]); $user = $stmt->fetch(PDO::FETCH_ASSOC); return $user ?: null; } public function create(array $data): array { $stmt = $this->pdo->prepare( 'INSERT INTO users (id, name, email, password, role) VALUES (:id, :name, :email, :password, :role) RETURNING *' ); $stmt->execute([ ':id' => uuid_create(), ':name' => $data['name'], ':email' => $data['email'], ':password' => password_hash($data['password'], PASSWORD_BCRYPT), ':role' => $data['role'] ?? UserRole::User->value, ]); return $stmt->fetch(PDO::FETCH_ASSOC); } public function paginate(int $page, int $perPage = 20): array { $offset = ($page - 1) * $perPage; $stmt = $this->pdo->prepare( 'SELECT id, name, email, role, is_active, created_at FROM users ORDER BY created_at DESC LIMIT :limit OFFSET :offset' ); $stmt->bindValue(':limit', $perPage, PDO::PARAM_INT); $stmt->bindValue(':offset', $offset, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } } ``` ### Step 6: Entry Point ```php <?php // public/index.php declare(strict_types=1);
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub