home / skills / pluginagentmarketplace / custom-plugin-php / php-api

php-api skill

/skills/php-api

This skill helps you design and implement PHP APIs (REST, GraphQL) with secure authentication and OpenAPI documentation for robust applications.

npx playbooks add skill pluginagentmarketplace/custom-plugin-php --skill php-api

Review the files below or copy the command above to add this skill to your agents.

Files (6)
SKILL.md
7.3 KB
---
name: php-api
version: "2.0.0"
description: PHP API development mastery - REST, GraphQL, JWT/OAuth, OpenAPI documentation
sasmp_version: "1.3.0"
bonded_agent: 07-php-api
bond_type: PRIMARY_BOND
atomic: true
category: integration
---

# PHP API Development Skill

> Atomic skill for mastering API design and implementation in PHP

## Overview

Comprehensive skill for PHP API development covering REST design, GraphQL, authentication strategies, and API documentation.

## Skill Parameters

### Input Validation
```typescript
interface SkillParams {
  topic:
    | "rest"             // RESTful API design
    | "graphql"          // GraphQL with PHP
    | "authentication"   // JWT, OAuth 2.0
    | "documentation"    // OpenAPI, Swagger
    | "versioning"       // API versioning strategies
    | "security";        // Rate limiting, CORS

  level: "beginner" | "intermediate" | "advanced";
  framework?: "laravel" | "symfony" | "slim";
  auth_method?: "jwt" | "oauth2" | "api_key";
}
```

### Validation Rules
```yaml
validation:
  topic:
    required: true
    allowed: [rest, graphql, authentication, documentation, versioning, security]
  level:
    required: true
  framework:
    default: "laravel"
```

## Learning Modules

### Module 1: REST API Design
```yaml
beginner:
  - Resource naming conventions
  - HTTP methods semantics
  - Status codes usage

intermediate:
  - Pagination patterns
  - Filtering and sorting
  - HATEOAS basics

advanced:
  - Hypermedia APIs
  - Conditional requests
  - Bulk operations
```

### Module 2: Authentication
```yaml
beginner:
  - API keys
  - Basic auth
  - Token basics

intermediate:
  - JWT implementation
  - Refresh tokens
  - Token revocation

advanced:
  - OAuth 2.0 flows
  - PKCE
  - Scopes and permissions
```

### Module 3: API Security
```yaml
beginner:
  - Input validation
  - Output encoding
  - CORS basics

intermediate:
  - Rate limiting
  - Request throttling
  - API versioning

advanced:
  - Security headers
  - Request signing
  - Audit logging
```

## Error Handling & Retry Logic

```yaml
errors:
  VALIDATION_ERROR:
    code: "API_001"
    http_status: 422
    recovery: "Return field-level errors"

  AUTH_ERROR:
    code: "API_002"
    http_status: 401
    recovery: "Check token, suggest refresh"

  RATE_LIMIT_ERROR:
    code: "API_003"
    http_status: 429
    recovery: "Return Retry-After header"

retry:
  max_attempts: 3
  backoff:
    type: exponential
    initial_delay_ms: 100
```

## Code Examples

### REST Controller (Laravel)
```php
<?php
declare(strict_types=1);

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Http\Requests\StoreUserRequest;
use App\Http\Resources\UserResource;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;

final class UserController extends Controller
{
    public function index()
    {
        $users = User::query()
            ->with(['profile'])
            ->filter(request(['search', 'status']))
            ->paginate(request('per_page', 15));

        return UserResource::collection($users);
    }

    public function store(StoreUserRequest $request): JsonResponse
    {
        $user = User::create($request->validated());

        return (new UserResource($user))
            ->response()
            ->setStatusCode(Response::HTTP_CREATED)
            ->header('Location', route('api.v1.users.show', $user));
    }

    public function show(User $user): UserResource
    {
        return new UserResource($user->load('profile'));
    }

    public function destroy(User $user): Response
    {
        $this->authorize('delete', $user);
        $user->delete();

        return response()->noContent();
    }
}
```

### Error Response (RFC 7807)
```php
<?php
declare(strict_types=1);

namespace App\Http\Responses;

final class ProblemDetails
{
    public static function validation(array $errors): array
    {
        return [
            'type' => 'https://api.example.com/errors/validation',
            'title' => 'Validation Error',
            'status' => 422,
            'detail' => 'The request contains invalid data',
            'errors' => $errors,
        ];
    }

    public static function unauthorized(): array
    {
        return [
            'type' => 'https://api.example.com/errors/unauthorized',
            'title' => 'Unauthorized',
            'status' => 401,
            'detail' => 'Authentication required',
        ];
    }
}
```

### JWT Authentication
```php
<?php
declare(strict_types=1);

namespace App\Services;

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

final class JwtService
{
    public function __construct(
        private readonly string $secret,
        private readonly string $algorithm = 'HS256',
        private readonly int $ttl = 3600,
    ) {}

    public function generate(array $payload): string
    {
        $issuedAt = time();

        return JWT::encode([
            ...$payload,
            'iat' => $issuedAt,
            'exp' => $issuedAt + $this->ttl,
        ], $this->secret, $this->algorithm);
    }

    public function decode(string $token): object
    {
        return JWT::decode($token, new Key($this->secret, $this->algorithm));
    }
}
```

### OpenAPI Specification
```yaml
openapi: 3.1.0
info:
  title: User API
  version: 1.0.0

paths:
  /api/v1/users:
    get:
      summary: List users
      parameters:
        - name: page
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserCollection'

    post:
      summary: Create user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUser'
      responses:
        '201':
          description: Created

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
        email:
          type: string
          format: email
        name:
          type: string

  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

security:
  - bearerAuth: []
```

### Rate Limiting (Laravel)
```php
<?php
// RouteServiceProvider or bootstrap/app.php
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

RateLimiter::for('api', function ($request) {
    return Limit::perMinute(60)
        ->by($request->user()?->id ?: $request->ip())
        ->response(function () {
            return response()->json([
                'type' => 'https://api.example.com/errors/rate-limit',
                'title' => 'Too Many Requests',
                'status' => 429,
            ], 429)->header('Retry-After', 60);
        });
});
```

## Troubleshooting

| Problem | Cause | Solution |
|---------|-------|----------|
| CORS errors | Missing headers | Configure CORS middleware |
| JWT invalid | Expired or wrong secret | Check exp claim, verify secret |
| 429 errors | Rate limited | Implement backoff, cache responses |
| N+1 in resources | Missing eager loading | Use with() in controller |

## Quality Metrics

| Metric | Target |
|--------|--------|
| Response time | <200ms P95 |
| Error rate | <0.1% |
| Documentation | 100% endpoints |
| Test coverage | ≥90% |

## Usage

```
Skill("php-api", {topic: "authentication", level: "intermediate"})
```

Overview

This skill teaches practical mastery of PHP API development across REST, GraphQL, authentication, and API documentation. It condenses patterns, code examples, and operational guidance for building secure, versioned APIs with Laravel, Symfony, or Slim. Use it to implement production-grade endpoints, tokens, rate limiting, and OpenAPI specs.

How this skill works

The skill inspects the selected topic and level to deliver focused guidance: architecture patterns, required middleware, and concrete code snippets (controllers, services, responses). It includes validation and error-handling conventions, JWT/OAuth examples, rate limiting, and an OpenAPI template to generate docs. Output targets actionable changes you can apply directly to a PHP project.

When to use it

  • Designing REST endpoints or GraphQL schemas for a new PHP service
  • Implementing JWT or OAuth2 authentication and token lifecycle
  • Adding API security: CORS, rate limiting, input validation, and headers
  • Generating OpenAPI documentation and publishing interactive docs
  • Enforcing API versioning and backward-compatible changes during releases

Best practices

  • Follow resource-based naming and standard HTTP semantics for REST
  • Return RFC 7807 problem details for structured error responses
  • Use short-lived JWTs with refresh tokens and server-side revocation
  • Eager-load relations (with()) and paginate responses to avoid N+1
  • Expose OpenAPI specs and protect admin endpoints with scopes
  • Apply rate limits per user/IP and include Retry-After headers

Example use cases

  • Create a Laravel API controller that returns paginated user resources with filters and HATEOAS links
  • Implement a JwtService to issue and validate tokens with exp and iat claims
  • Define OpenAPI 3.1 documentation for user endpoints and attach bearerAuth security
  • Add rate limiting in RouteServiceProvider to return a structured 429 response
  • Migrate an API to versioned routes (/api/v1/) with backward-compatible controllers

FAQ

Which framework should I choose for APIs?

Laravel provides full-featured tools and resource controllers; Symfony is ideal for strict architecture; Slim suits microservices. Pick based on team familiarity and ecosystem needs.

How do I handle token revocation?

Store active refresh tokens or a token blacklist with expiration. Invalidate tokens on logout and check revocation during auth middleware.

What error format should I return?

Use RFC 7807 Problem Details for machine-readable errors and include an errors field for field-level validation messages.