Skip to content

APIs and Interfaces

Overview

APIs (Application Programming Interfaces) and interfaces are key concepts in PHP development. This chapter covers object-oriented interfaces, interacting with Web APIs, creating RESTful services, and consuming external APIs. Understanding these concepts is essential for building modern, interconnected applications.

Object-Oriented Interfaces

Basic Interface Definition

php
<?php
// Interface definition
interface PaymentProcessorInterface {
    public function processPayment($amount, $currency);
    public function refundPayment($transactionId);
    public function getTransactionStatus($transactionId);
}

// Interface implementation
class StripePaymentProcessor implements PaymentProcessorInterface {
    private $apiKey;
    
    public function __construct($apiKey) {
        $this->apiKey = $apiKey;
    }
    
    public function processPayment($amount, $currency) {
        // Stripe-specific payment processing
        return [
            'success' => true,
            'transaction_id' => 'stripe_' . uniqid(),
            'amount' => $amount,
            'currency' => $currency
        ];
    }
    
    public function refundPayment($transactionId) {
        // Stripe-specific refund logic
        return [
            'success' => true,
            'refund_id' => 'refund_' . uniqid(),
            'transaction_id' => $transactionId
        ];
    }
    
    public function getTransactionStatus($transactionId) {
        // Stripe-specific status check
        return 'Completed';
    }
}

class PayPalPaymentProcessor implements PaymentProcessorInterface {
    private $clientId;
    private $clientSecret;
    
    public function __construct($clientId, $clientSecret) {
        $this->clientId = $clientId;
        $this->clientSecret = $clientSecret;
    }
    
    public function processPayment($amount, $currency) {
        // PayPal-specific payment processing
        return [
            'success' => true,
            'transaction_id' => 'paypal_' . uniqid(),
            'amount' => $amount,
            'currency' => $currency
        ];
    }
    
    public function refundPayment($transactionId) {
        // PayPal-specific refund logic
        return [
            'success' => true,
            'refund_id' => 'pp_refund_' . uniqid(),
            'transaction_id' => $transactionId
        ];
    }
    
    public function getTransactionStatus($transactionId) {
        // PayPal-specific status check
        return 'Pending';
    }
}

// Using polymorphism
function processOrder($processor, $amount, $currency) {
    if (!$processor instanceof PaymentProcessorInterface) {
        throw new InvalidArgumentException('Processor must implement PaymentProcessorInterface');
    }
    
    $result = $processor->processPayment($amount, $currency);
    
    if ($result['success']) {
        echo "Payment processed successfully: {$result['transaction_id']}\n";
        return $result['transaction_id'];
    } else {
        echo "Payment failed\n";
        return false;
    }
}

$stripeProcessor = new StripePaymentProcessor('sk_test_123');
$paypalProcessor = new PayPalPaymentProcessor('client_123', 'secret_456');

processOrder($stripeProcessor, 100.00, 'USD');
processOrder($paypalProcessor, 75.50, 'EUR');
?>

Multiple Interface Implementation

php
<?php
interface Readable {
    public function read();
}

interface Writable {
    public function write($data);
}

interface Seekable {
    public function seek($position);
    public function tell();
}

// Class implementing multiple interfaces
class FileHandler implements Readable, Writable, Seekable {
    private $file;
    private $position = 0;
    
    public function __construct($filename, $mode = 'r+') {
        $this->file = fopen($filename, $mode);
        if (!$this->file) {
            throw new Exception("Cannot open file: $filename");
        }
    }
    
    public function read() {
        return fread($this->file, 1024);
    }
    
    public function write($data) {
        return fwrite($this->file, $data);
    }
    
    public function seek($position) {
        $this->position = $position;
        return fseek($this->file, $position);
    }
    
    public function tell() {
        return ftell($this->file);
    }
    
    public function __destruct() {
        if ($this->file) {
            fclose($this->file);
        }
    }
}

// Interface inheritance
interface DatabaseConnectionInterface {
    public function connect();
    public function disconnect();
}

interface QueryableInterface extends DatabaseConnectionInterface {
    public function query($sql);
    public function prepare($sql);
}

interface TransactionalInterface extends QueryableInterface {
    public function beginTransaction();
    public function commit();
    public function rollback();
}

class MySQLConnection implements TransactionalInterface {
    private $connection;
    private $inTransaction = false;
    
    public function connect() {
        // MySQL connection logic
        echo "Connected to MySQL\n";
    }
    
    public function disconnect() {
        // MySQL disconnection logic
        echo "Disconnected from MySQL\n";
    }
    
    public function query($sql) {
        echo "Executing query: $sql\n";
        return ['result' => 'data'];
    }
    
    public function prepare($sql) {
        echo "Preparing statement: $sql\n";
        return new stdClass(); // Simulate prepared statement
    }
    
    public function beginTransaction() {
        $this->inTransaction = true;
        echo "Transaction started\n";
    }
    
    public function commit() {
        if ($this->inTransaction) {
            $this->inTransaction = false;
            echo "Transaction committed\n";
        }
    }
    
    public function rollback() {
        if ($this->inTransaction) {
            $this->inTransaction = false;
            echo "Transaction rolled back\n";
        }
    }
}
?>

Interface Constants and Type Hints

php
<?php
interface LoggerInterface {
    const LEVEL_DEBUG = 1;
    const LEVEL_INFO = 2;
    const LEVEL_WARNING = 3;
    const LEVEL_ERROR = 4;
    const LEVEL_CRITICAL = 5;
    
    public function log($level, $message, array $context = []);
}

class FileLogger implements LoggerInterface {
    private $logFile;
    
    public function __construct($logFile) {
        $this->logFile = $logFile;
    }
    
    public function log($level, $message, array $context = []) {
        $levelNames = [
            self::LEVEL_DEBUG => 'DEBUG',
            self::LEVEL_INFO => 'INFO',
            self::LEVEL_WARNING => 'WARNING',
            self::LEVEL_ERROR => 'ERROR',
            self::LEVEL_CRITICAL => 'CRITICAL'
        ];
        
        $levelName = $levelNames[$level] ?? 'UNKNOWN';
        $timestamp = date('Y-m-d H:i:s');
        $contextStr = !empty($context) ? json_encode($context) : '';
        
        $logEntry = "[$timestamp] [$levelName] $message $contextStr\n";
        file_put_contents($this->logFile, $logEntry, FILE_APPEND | LOCK_EX);
    }
}

// Using interface for type hints
class Application {
    private $logger;
    
    public function __construct(LoggerInterface $logger) {
        $this->logger = $logger;
    }
    
    public function run() {
        $this->logger->log(LoggerInterface::LEVEL_INFO, 'Application started');
        
        try {
            // Application logic
            $this->processData();
        } catch (Exception $e) {
            $this->logger->log(
                LoggerInterface::LEVEL_ERROR, 
                'Application error: ' . $e->getMessage(),
                ['exception' => get_class($e), 'file' => $e->getFile(), 'line' => $e->getLine()]
            );
        }
        
        $this->logger->log(LoggerInterface::LEVEL_INFO, 'Application ended');
    }
    
    private function processData() {
        $this->logger->log(LoggerInterface::LEVEL_DEBUG, 'Processing data');
        // Processing logic here
    }
}

$logger = new FileLogger('app.log');
$app = new Application($logger);
$app->run();
?>

Interacting with Web APIs

Sending HTTP Requests

php
<?php
// Using cURL to send HTTP requests
class HttpClient {
    private $baseUrl;
    private $defaultHeaders;
    
    public function __construct($baseUrl = '', $defaultHeaders = []) {
        $this->baseUrl = rtrim($baseUrl, '/');
        $this->defaultHeaders = $defaultHeaders;
    }
    
    public function get($endpoint, $headers = []) {
        return $this->makeRequest('GET', $endpoint, null, $headers);
    }
    
    public function post($endpoint, $data = null, $headers = []) {
        return $this->makeRequest('POST', $endpoint, $data, $headers);
    }
    
    public function put($endpoint, $data = null, $headers = []) {
        return $this->makeRequest('PUT', $endpoint, $data, $headers);
    }
    
    public function delete($endpoint, $headers = []) {
        return $this->makeRequest('DELETE', $endpoint, null, $headers);
    }
    
    private function makeRequest($method, $endpoint, $data = null, $headers = []) {
        $url = $this->baseUrl . '/' . ltrim($endpoint, '/');
        $allHeaders = array_merge($this->defaultHeaders, $headers);
        
        $curl = curl_init();
        
        curl_setopt_array($curl, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_HTTPHEADER => $this->formatHeaders($allHeaders),
            CURLOPT_TIMEOUT => 30,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_SSL_VERIFYPEER => false, // Only for development
        ]);
        
        if ($data !== null) {
            if (is_array($data) || is_object($data)) {
                curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
                $allHeaders['Content-Type'] = 'application/json';
            } else {
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            }
        }
        
        $response = curl_exec($curl);
        $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $error = curl_error($curl);
        
        curl_close($curl);
        
        if ($error) {
            throw new Exception("cURL error: $error");
        }
        
        return [
            'status_code' => $httpCode,
            'body' => $response,
            'data' => json_decode($response, true)
        ];
    }
    
    private function formatHeaders($headers) {
        $formatted = [];
        foreach ($headers as $key => $value) {
            $formatted[] = "$key: $value";
        }
        return $formatted;
    }
}

// Usage example
$client = new HttpClient('https://jsonplaceholder.typicode.com', [
    'User-Agent' => 'PHP HTTP Client 1.0'
]);

try {
    // GET request
    $response = $client->get('/posts/1');
    echo "Status: {$response['status_code']}\n";
    echo "Title: {$response['data']['title']}\n";
    
    // POST request
    $newPost = [
        'title' => 'My New Post',
        'body' => 'This is the content of my new post.',
        'userId' => 1
    ];
    
    $response = $client->post('/posts', $newPost);
    echo "Created post ID: {$response['data']['id']}\n";
    
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
?>

API Response Handling

php
<?php
class ApiResponse {
    private $statusCode;
    private $headers;
    private $body;
    private $data;
    
    public function __construct($statusCode, $headers, $body) {
        $this->statusCode = $statusCode;
        $this->headers = $headers;
        $this->body = $body;
        $this->data = json_decode($body, true);
    }
    
    public function isSuccessful() {
        return $this->statusCode >= 200 && $this->statusCode < 300;
    }
    
    public function isClientError() {
        return $this->statusCode >= 400 && $this->statusCode < 500;
    }
    
    public function isServerError() {
        return $this->statusCode >= 500;
    }
    
    public function getStatusCode() {
        return $this->statusCode;
    }
    
    public function getHeaders() {
        return $this->headers;
    }
    
    public function getBody() {
        return $this->body;
    }
    
    public function getData() {
        return $this->data;
    }
    
    public function getHeader($name) {
        return $this->headers[$name] ?? null;
    }
}

// API client with response handling
class WeatherApiClient {
    private $httpClient;
    private $apiKey;
    
    public function __construct($apiKey) {
        $this->apiKey = $apiKey;
        $this->httpClient = new HttpClient('https://api.openweathermap.org/data/2.5');
    }
    
    public function getCurrentWeather($city) {
        try {
            $response = $this->httpClient->get("/weather", [
                'q' => $city,
                'appid' => $this->apiKey,
                'units' => 'metric'
            ]);
            
            if ($response['status_code'] === 200) {
                return [
                    'success' => true,
                    'data' => [
                        'city' => $response['data']['name'],
                        'temperature' => $response['data']['main']['temp'],
                        'description' => $response['data']['weather'][0]['description'],
                        'humidity' => $response['data']['main']['humidity']
                    ]
                ];
            } else {
                return [
                    'success' => false,
                    'error' => $response['data']['message'] ?? 'Unknown error'
                ];
            }
        } catch (Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }
    
    public function getForecast($city, $days = 5) {
        try {
            $response = $this->httpClient->get("/forecast", [
                'q' => $city,
                'appid' => $this->apiKey,
                'units' => 'metric',
                'cnt' => $days * 8 // 8 forecasts per day (every 3 hours)
            ]);
            
            if ($response['status_code'] === 200) {
                $forecasts = [];
                foreach ($response['data']['list'] as $item) {
                    $forecasts[] = [
                        'datetime' => $item['dt_txt'],
                        'temperature' => $item['main']['temp'],
                        'description' => $item['weather'][0]['description']
                    ];
                }
                
                return [
                    'success' => true,
                    'data' => [
                        'city' => $response['data']['city']['name'],
                        'forecasts' => $forecasts
                    ]
                ];
            } else {
                return [
                    'success' => false,
                    'error' => $response['data']['message'] ?? 'Unknown error'
                ];
            }
        } catch (Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }
}

// Usage
$weatherClient = new WeatherApiClient('your_api_key_here');

$currentWeather = $weatherClient->getCurrentWeather('London');
if ($currentWeather['success']) {
    $data = $currentWeather['data'];
    echo "{$data['city']} current weather: {$data['temperature']}°C, {$data['description']}\n";
} else {
    echo "Error: {$currentWeather['error']}\n";
}
?>

Creating RESTful APIs

Basic REST API Structure

php
<?php
// Simple REST API router
class RestApiRouter {
    private $routes = [];
    
    public function get($path, $handler) {
        $this->addRoute('GET', $path, $handler);
    }
    
    public function post($path, $handler) {
        $this->addRoute('POST', $path, $handler);
    }
    
    public function put($path, $handler) {
        $this->addRoute('PUT', $path, $handler);
    }
    
    public function delete($path, $handler) {
        $this->addRoute('DELETE', $path, $handler);
    }
    
    private function addRoute($method, $path, $handler) {
        $this->routes[] = [
            'method' => $method,
            'path' => $path,
            'handler' => $handler
        ];
    }
    
    public function handle() {
        $method = $_SERVER['REQUEST_METHOD'];
        $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
        
        foreach ($this->routes as $route) {
            if ($route['method'] === $method && $this->matchPath($route['path'], $path)) {
                $params = $this->extractParams($route['path'], $path);
                return call_user_func($route['handler'], $params);
            }
        }
        
        $this->sendResponse(404, ['error' => 'Route not found']);
    }
    
    private function matchPath($routePath, $requestPath) {
        $routePattern = preg_replace('/\{[^}]+\}/', '([^/]+)', $routePath);
        return preg_match("#^{$routePattern}$#", $requestPath);
    }
    
    private function extractParams($routePath, $requestPath) {
        $params = [];
        $routeParts = explode('/', $routePath);
        $requestParts = explode('/', $requestPath);
        
        for ($i = 0; $i < count($routeParts); $i++) {
            if (preg_match('/\{([^}]+)\}/', $routeParts[$i], $matches)) {
                $paramName = $matches[1];
                $params[$paramName] = $requestParts[$i] ?? null;
            }
        }
        
        return $params;
    }
    
    private function sendResponse($statusCode, $data) {
        http_response_code($statusCode);
        header('Content-Type: application/json');
        echo json_encode($data);
        exit;
    }
}

// User API controller
class UserApiController {
    private $users = [
        1 => ['id' => 1, 'name' => 'Zhang San', 'email' => 'zhangsan@example.com'],
        2 => ['id' => 2, 'name' => 'Li Si', 'email' => 'lisi@example.com'],
        3 => ['id' => 3, 'name' => 'Wang Wu', 'email' => 'wangwu@example.com']
    ];
    
    public function getAllUsers($params) {
        $this->sendResponse(200, array_values($this->users));
    }
    
    public function getUser($params) {
        $id = (int)$params['id'];
        
        if (isset($this->users[$id])) {
            $this->sendResponse(200, $this->users[$id]);
        } else {
            $this->sendResponse(404, ['error' => 'User not found']);
        }
    }
    
    public function createUser($params) {
        $input = json_decode(file_get_contents('php://input'), true);
        
        if (!$input || !isset($input['name']) || !isset($input['email'])) {
            $this->sendResponse(400, ['error' => 'Name and email are required']);
        }
        
        $id = max(array_keys($this->users)) + 1;
        $user = [
            'id' => $id,
            'name' => $input['name'],
            'email' => $input['email']
        ];
        
        $this->users[$id] = $user;
        $this->sendResponse(201, $user);
    }
    
    public function updateUser($params) {
        $id = (int)$params['id'];
        $input = json_decode(file_get_contents('php://input'), true);
        
        if (!isset($this->users[$id])) {
            $this->sendResponse(404, ['error' => 'User not found']);
        }
        
        if ($input) {
            if (isset($input['name'])) {
                $this->users[$id]['name'] = $input['name'];
            }
            if (isset($input['email'])) {
                $this->users[$id]['email'] = $input['email'];
            }
        }
        
        $this->sendResponse(200, $this->users[$id]);
    }
    
    public function deleteUser($params) {
        $id = (int)$params['id'];
        
        if (isset($this->users[$id])) {
            unset($this->users[$id]);
            $this->sendResponse(204, null);
        } else {
            $this->sendResponse(404, ['error' => 'User not found']);
        }
    }
    
    private function sendResponse($statusCode, $data) {
        http_response_code($statusCode);
        header('Content-Type: application/json');
        
        if ($data !== null) {
            echo json_encode($data);
        }
        
        exit;
    }
}

// API setup
$router = new RestApiRouter();
$userController = new UserApiController();

// Define routes
$router->get('/api/users', [$userController, 'getAllUsers']);
$router->get('/api/users/{id}', [$userController, 'getUser']);
$router->post('/api/users', [$userController, 'createUser']);
$router->put('/api/users/{id}', [$userController, 'updateUser']);
$router->delete('/api/users/{id}', [$userController, 'deleteUser']);

// Handle request
$router->handle();
?>

API Authentication and Middleware

php
<?php
// JWT token handler (simplified)
class JwtHandler {
    private $secret;
    
    public function __construct($secret) {
        $this->secret = $secret;
    }
    
    public function generateToken($payload) {
        $header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']);
        $payload = json_encode($payload);
        
        $base64Header = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
        $base64Payload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));
        
        $signature = hash_hmac('sha256', $base64Header . "." . $base64Payload, $this->secret, true);
        $base64Signature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
        
        return $base64Header . "." . $base64Payload . "." . $base64Signature;
    }
    
    public function validateToken($token) {
        $parts = explode('.', $token);
        
        if (count($parts) !== 3) {
            return false;
        }
        
        [$header, $payload, $signature] = $parts;
        
        $validSignature = hash_hmac('sha256', $header . "." . $payload, $this->secret, true);
        $validBase64Signature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($validSignature));
        
        if ($signature !== $validBase64Signature) {
            return false;
        }
        
        $decodedPayload = json_decode(base64_decode(str_replace(['-', '_'], ['+', '/'], $payload)), true);
        
        // Check expiration
        if (isset($decodedPayload['exp']) && $decodedPayload['exp'] < time()) {
            return false;
        }
        
        return $decodedPayload;
    }
}

// Authentication middleware
class AuthMiddleware {
    private $jwtHandler;
    
    public function __construct(JwtHandler $jwtHandler) {
        $this->jwtHandler = $jwtHandler;
    }
    
    public function authenticate() {
        $headers = getallheaders();
        $authHeader = $headers['Authorization'] ?? '';
        
        if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) {
            $this->sendUnauthorized('Missing or invalid authorization header');
        }
        
        $token = $matches[1];
        $payload = $this->jwtHandler->validateToken($token);
        
        if (!$payload) {
            $this->sendUnauthorized('Invalid or expired token');
        }
        
        return $payload;
    }
    
    private function sendUnauthorized($message) {
        http_response_code(401);
        header('Content-Type: application/json');
        echo json_encode(['error' => $message]);
        exit;
    }
}

// Protected API controller
class ProtectedApiController {
    private $authMiddleware;
    
    public function __construct(AuthMiddleware $authMiddleware) {
        $this->authMiddleware = $authMiddleware;
    }
    
    public function getProfile($params) {
        $user = $this->authMiddleware->authenticate();
        
        // Return user profile
        $this->sendResponse(200, [
            'id' => $user['user_id'],
            'name' => $user['name'],
            'email' => $user['email']
        ]);
    }
    
    public function updateProfile($params) {
        $user = $this->authMiddleware->authenticate();
        $input = json_decode(file_get_contents('php://input'), true);
        
        // Update user profile logic here
        
        $this->sendResponse(200, ['message' => 'Profile updated successfully']);
    }
    
    private function sendResponse($statusCode, $data) {
        http_response_code($statusCode);
        header('Content-Type: application/json');
        echo json_encode($data);
        exit;
    }
}

// Login controller
class AuthController {
    private $jwtHandler;
    private $users = [
        'zhangsan@example.com' => ['id' => 1, 'name' => 'Zhang San', 'password' => 'password123'],
        'lisi@example.com' => ['id' => 2, 'name' => 'Li Si', 'password' => 'secret456']
    ];
    
    public function __construct(JwtHandler $jwtHandler) {
        $this->jwtHandler = $jwtHandler;
    }
    
    public function login($params) {
        $input = json_decode(file_get_contents('php://input'), true);
        
        if (!isset($input['email']) || !isset($input['password'])) {
            $this->sendResponse(400, ['error' => 'Email and password are required']);
        }
        
        $email = $input['email'];
        $password = $input['password'];
        
        if (!isset($this->users[$email]) || $this->users[$email]['password'] !== $password) {
            $this->sendResponse(401, ['error' => 'Invalid credentials']);
        }
        
        $user = $this->users[$email];
        $payload = [
            'user_id' => $user['id'],
            'name' => $user['name'],
            'email' => $email,
            'exp' => time() + 3600 // 1 hour expiration
        ];
        
        $token = $this->jwtHandler->generateToken($payload);
        
        $this->sendResponse(200, [
            'token' => $token,
            'user' => [
                'id' => $user['id'],
                'name' => $user['name'],
                'email' => $email
            ]
        ]);
    }
    
    private function sendResponse($statusCode, $data) {
        http_response_code($statusCode);
        header('Content-Type: application/json');
        echo json_encode($data);
        exit;
    }
}

// Setup
$jwtHandler = new JwtHandler('your-secret-key');
$authMiddleware = new AuthMiddleware($jwtHandler);
$authController = new AuthController($jwtHandler);
$protectedController = new ProtectedApiController($authMiddleware);

// Routes
$router = new RestApiRouter();
$router->post('/api/login', [$authController, 'login']);
$router->get('/api/profile', [$protectedController, 'getProfile']);
$router->put('/api/profile', [$protectedController, 'updateProfile']);

$router->handle();
?>

API Documentation and Testing

API Documentation Generator

php
<?php
/**
 * @api {get} /api/users Get all users
 * @apiName GetUsers
 * @apiGroup User
 * 
 * @apiSuccess {Object[]} users User list
 * @apiSuccess {Number} users.id User ID
 * @apiSuccess {String} users.name User name
 * @apiSuccess {String} users.email User email
 * 
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     [
 *       {
 *         "id": 1,
 *         "name": "Zhang San",
 *         "email": "zhangsan@example.com"
 *       }
 *     ]
 */

class ApiDocumentationGenerator {
    private $routes = [];
    
    public function addRoute($method, $path, $description, $parameters = [], $responses = []) {
        $this->routes[] = [
            'method' => strtoupper($method),
            'path' => $path,
            'description' => $description,
            'parameters' => $parameters,
            'responses' => $responses
        ];
    }
    
    public function generateHtml() {
        $html = '<!DOCTYPE html>
<html>
<head>
    <title>API Documentation</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .route { margin-bottom: 30px; border: 1px solid #ddd; padding: 20px; }
        .method { display: inline-block; padding: 5px 10px; color: white; font-weight: bold; }
        .get { background-color: #61affe; }
        .post { background-color: #49cc90; }
        .put { background-color: #fca130; }
        .delete { background-color: #f93e3e; }
        .path { font-family: monospace; font-size: 18px; margin-left: 10px; }
        .parameters, .responses { margin-top: 15px; }
        table { width: 100%; border-collapse: collapse; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <h1>API Documentation</h1>';
        
        foreach ($this->routes as $route) {
            $methodClass = strtolower($route['method']);
            $html .= "<div class='route'>";
            $html .= "<span class='method {$methodClass}'>{$route['method']}</span>";
            $html .= "<span class='path'>{$route['path']}</span>";
            $html .= "<p>{$route['description']}</p>";
            
            if (!empty($route['parameters'])) {
                $html .= "<div class='parameters'><h4>Parameters:</h4>";
                $html .= "<table><tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>";
                foreach ($route['parameters'] as $param) {
                    $required = $param['required'] ? 'Yes' : 'No';
                    $html .= "<tr><td>{$param['name']}</td><td>{$param['type']}</td><td>{$required}</td><td>{$param['description']}</td></tr>";
                }
                $html .= "</table></div>";
            }
            
            if (!empty($route['responses'])) {
                $html .= "<div class='responses'><h4>Responses:</h4>";
                foreach ($route['responses'] as $response) {
                    $html .= "<h5>HTTP {$response['code']}</h5>";
                    $html .= "<pre>" . htmlspecialchars($response['example']) . "</pre>";
                }
                $html .= "</div>";
            }
            
            $html .= "</div>";
        }
        
        $html .= '</body></html>';
        return $html;
    }
}

// Usage
$docs = new ApiDocumentationGenerator();

$docs->addRoute('GET', '/api/users', 'Get all users', [], [
    ['code' => 200, 'example' => json_encode([
        ['id' => 1, 'name' => 'Zhang San', 'email' => 'zhangsan@example.com']
    ], JSON_PRETTY_PRINT)]
]);

$docs->addRoute('POST', '/api/users', 'Create new user', [
    ['name' => 'name', 'type' => 'string', 'required' => true, 'description' => 'User name'],
    ['name' => 'email', 'type' => 'string', 'required' => true, 'description' => 'User email']
], [
    ['code' => 201, 'example' => json_encode([
        'id' => 4, 'name' => 'New User', 'email' => 'new@example.com'
    ], JSON_PRETTY_PRINT)]
]);

echo $docs->generateHtml();
?>

Next Steps

Now that you understand APIs and interfaces, let's explore error handling in Error Handling.

Practice Exercises

  1. Create a complete RESTful API for a blog system
  2. Build API clients for popular web services (GitHub, Twitter, etc.)
  3. Implement API rate limiting and caching
  4. Create an API gateway that routes requests to different services
  5. Build a webhook system for real-time notifications

Understanding APIs and interfaces is essential for building modern, interconnected PHP applications!

Content is for learning and research only.