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.

معلومات المصدر

المستودع
j4flmao/agent-skills
آخر نشاط في المصدر
٦ سبتمبر ٢٠٢٦ في ١٣:٤٥
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٢٧
التفرعات
١

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
7 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
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);
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub