Inicio > Cursos > PHP > Proyecto: API REST con PHP
PHPPOO y PHP ModernoLección 13 de 15

Proyecto: API REST con PHP

Este proyecto construye una API REST completa con PHP puro (sin frameworks), aplicando todo lo aprendido: manejo de rutas según la URL ($_SERVER["REQUEST_URI"]), lectura del método HTTP ($_SERVER["REQUEST_METHOD"]), recepción de JSON del body (json_decode(file_get_contents("php://input"))), acceso a la base de datos con PDO y prepared statements, y respuestas JSON con header("Content-Type: application/json"). Este es el núcleo de cómo funcionan frameworks como Laravel internamente.

Construir una API sin framework te enseña los fundamentos que los frameworks abstraen: cómo el servidor HTTP comunica la solicitud a PHP mediante variables superglobales ($_SERVER, $_GET, $_POST), cómo las respuestas HTTP tienen códigos de estado significativos (200 OK, 201 Created, 404 Not Found, 400 Bad Request), y cómo manejar errores devolviendo JSON en lugar de páginas de error.

Una vez que entiendes estos fundamentos, aprender Laravel es mucho más sencillo porque sabes qué está haciendo por ti.

<?php
// index.php - API REST con PHP puro
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE");

$method = $_SERVER["REQUEST_METHOD"];
$uri = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
$parts = explode("/", trim($uri, "/"));
$resource = $parts[1] ?? "";
$id = isset($parts[2]) ? (int)$parts[2] : null;

function getDb(): PDO {
    static $pdo = null;
    if ($pdo === null) {
        $pdo = new PDO("sqlite:api.db", options: [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
        ]);
        $pdo->exec("CREATE TABLE IF NOT EXISTS tareas (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            titulo TEXT NOT NULL,
            completada INTEGER DEFAULT 0
        )");
    }
    return $pdo;
}

function responder(mixed $data, int $code = 200): never {
    http_response_code($code);
    echo json_encode($data, JSON_UNESCAPED_UNICODE);
    exit;
}

function body(): array {
    return json_decode(file_get_contents("php://input"), true) ?? [];
}

if ($resource === "tareas") {
    $db = getDb();
    
    match($method) {
        "GET" => $id
            ? (($t = $db->prepare("SELECT * FROM tareas WHERE id=?")->execute([$id]))
                ? responder($t) : responder(["error"=>"No encontrada"], 404))
            : responder($db->query("SELECT * FROM tareas")->fetchAll()),
        
        "POST" => (function() use ($db) {
            $b = body();
            if (empty($b["titulo"])) responder(["error"=>"Título requerido"], 400);
            $db->prepare("INSERT INTO tareas (titulo) VALUES (?)")->execute([$b["titulo"]]);
            responder(["id"=>$db->lastInsertId(), "titulo"=>$b["titulo"]], 201);
        })(),
        
        "DELETE" => (function() use ($db, $id) {
            if (!$id) responder(["error"=>"ID requerido"], 400);
            $db->prepare("DELETE FROM tareas WHERE id=?")->execute([$id]);
            responder(["ok" => true]);
        })(),
        
        default => responder(["error"=>"Método no permitido"], 405)
    };
}

responder(["error"=>"Ruta no encontrada"], 404);
Consejo🚀 Para proyectos reales, usa Laravel o Slim Framework. Laravel tiene routing, ORM (Eloquent), autenticación, validación y más, integrado desde el inicio.
← Seguridad Web: XSS y ValidaciónPatrón MVC desde Cero →

Practica esta lección

Resuelve los ejercicios del curso de PHP en la app, gratis y con corrección automática.

Empezar a practicar