Leccion 74 de 75 15 min de lectura

APIs REST

Las APIs permiten que diferentes aplicaciones se comuniquen entre si. REST es el estilo mas comun para crear APIs web. Con lo que has aprendido, puedes empezar a crear las tuyas.

Que es una API REST

Una API (Application Programming Interface) es un conjunto de endpoints que permiten a otras aplicaciones interactuar con la tuya. REST (Representational State Transfer) es un estilo arquitectonico que usa HTTP y JSON para esta comunicacion.

Ejemplos de uso de APIs:

  • Una app movil que obtiene datos de tu servidor PHP
  • Un frontend en React/Vue que consume datos de tu backend
  • Integracion entre diferentes sistemas

Metodos HTTP

REST usa los metodos HTTP para indicar la accion a realizar:

  • GET: Obtener datos (leer)
  • POST: Crear un nuevo recurso
  • PUT/PATCH: Actualizar un recurso existente
  • DELETE: Eliminar un recurso
Texto
Ejemplos de endpoints REST para usuarios:

GET    /api/usuarios       -> Listar todos los usuarios
GET    /api/usuarios/5     -> Obtener usuario con ID 5
POST   /api/usuarios       -> Crear nuevo usuario
PUT    /api/usuarios/5     -> Actualizar usuario 5
DELETE /api/usuarios/5     -> Eliminar usuario 5

Respuestas JSON

Las APIs REST tipicamente devuelven datos en formato JSON. PHP facilita esto con json_encode().

PHP
<?php

declare(strict_types=1);

// Indicar que la respuesta es JSON
header('Content-Type: application/json');

$usuario = [
    'id' => 1,
    'nombre' => 'Ana Garcia',
    'email' => 'ana@ejemplo.com',
];

echo json_encode($usuario);

// Salida:
// {"id":1,"nombre":"Ana Garcia","email":"ana@ejemplo.com"}

Codigos de estado HTTP

Los codigos de estado indican el resultado de la operacion:

  • 200 OK: Operacion exitosa
  • 201 Created: Recurso creado
  • 400 Bad Request: Error en los datos enviados
  • 404 Not Found: Recurso no encontrado
  • 500 Internal Server Error: Error del servidor
PHP
<?php

declare(strict_types=1);

header('Content-Type: application/json');

// Establecer codigo de estado
http_response_code(404);

echo json_encode([
    'error' => true,
    'mensaje' => 'Usuario no encontrado',
]);

Ejemplo: API simple de productos

Veamos como crear una API basica que maneja productos:

PHP
<?php
// api.php

declare(strict_types=1);

header('Content-Type: application/json');

// Datos de ejemplo (en una app real vendrian de la BD)
$productos = [
    1 => ['id' => 1, 'nombre' => 'Laptop', 'precio' => 999.99],
    2 => ['id' => 2, 'nombre' => 'Mouse', 'precio' => 29.99],
    3 => ['id' => 3, 'nombre' => 'Teclado', 'precio' => 79.99],
];

// Obtener metodo HTTP y ruta
$metodo = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];

// Extraer ID si existe en la URL (ej: /api.php/2)
$id = null;
if (preg_match('/\/api\.php\/(\d+)/', $uri, $matches)) {
    $id = (int) $matches[1];
}

// Router simple
switch ($metodo) {
    case 'GET':
        if ($id !== null) {
            // Obtener un producto
            if (isset($productos[$id])) {
                echo json_encode($productos[$id]);
            } else {
                http_response_code(404);
                echo json_encode(['error' => 'Producto no encontrado']);
            }
        } else {
            // Listar todos
            echo json_encode(array_values($productos));
        }
        break;

    case 'POST':
        // Crear producto
        $datos = json_decode(file_get_contents('php://input'), true);

        if (empty($datos['nombre']) || !isset($datos['precio'])) {
            http_response_code(400);
            echo json_encode(['error' => 'Nombre y precio son requeridos']);
            break;
        }

        $nuevoId = max(array_keys($productos)) + 1;
        $nuevoProducto = [
            'id' => $nuevoId,
            'nombre' => $datos['nombre'],
            'precio' => (float) $datos['precio'],
        ];

        http_response_code(201);
        echo json_encode($nuevoProducto);
        break;

    case 'DELETE':
        if ($id !== null && isset($productos[$id])) {
            http_response_code(200);
            echo json_encode(['mensaje' => 'Producto eliminado']);
        } else {
            http_response_code(404);
            echo json_encode(['error' => 'Producto no encontrado']);
        }
        break;

    default:
        http_response_code(405);
        echo json_encode(['error' => 'Metodo no permitido']);
}

Recibir datos JSON

Cuando un cliente envia datos JSON (por ejemplo, al crear un recurso), los recibes con php://input:

PHP
<?php

declare(strict_types=1);

// Leer el body de la peticion
$jsonRecibido = file_get_contents('php://input');

// Decodificar JSON a array asociativo
$datos = json_decode($jsonRecibido, true);

// Verificar que se decodifico correctamente
if ($datos === null && json_last_error() !== JSON_ERROR_NONE) {
    http_response_code(400);
    echo json_encode(['error' => 'JSON invalido']);
    exit;
}

// Usar los datos
$nombre = $datos['nombre'] ?? '';
$email = $datos['email'] ?? '';

CORS para APIs publicas

Si tu API será consumida desde un navegador en otro dominio, necesitas configurar CORS (Cross-Origin Resource Sharing):

PHP
<?php

declare(strict_types=1);

// Permitir peticiones desde cualquier origen
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
header('Access-Control-Allow-Headers: Content-Type');
header('Content-Type: application/json');

// Manejar preflight requests
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}

// ... resto de la API
Seguridad

En produccion, no uses * para CORS. Especifica los dominios permitidos exactos.

Ejercicios

Ejercicio 1: Respuesta JSON

Crea un script que devuelva una lista de 3 libros en formato JSON. Cada libro debe tener: id, titulo, autor y paginas.

Ver solucion
PHP
<?php

declare(strict_types=1);

header('Content-Type: application/json');

$libros = [
    [
        'id' => 1,
        'titulo' => 'Don Quijote de la Mancha',
        'autor' => 'Miguel de Cervantes',
        'paginas' => 863,
    ],
    [
        'id' => 2,
        'titulo' => 'Cien anos de soledad',
        'autor' => 'Gabriel Garcia Marquez',
        'paginas' => 471,
    ],
    [
        'id' => 3,
        'titulo' => '1984',
        'autor' => 'George Orwell',
        'paginas' => 328,
    ],
];

echo json_encode($libros, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);

Ejercicio 2: Manejar errores

Crea una funcion que busque un usuario por ID en un array. Si no existe, devuelve error 404 con mensaje JSON. Si existe, devuelve el usuario.

Ver solucion
PHP
<?php

declare(strict_types=1);

header('Content-Type: application/json');

$usuarios = [
    1 => ['id' => 1, 'nombre' => 'Ana', 'email' => 'ana@test.com'],
    2 => ['id' => 2, 'nombre' => 'Juan', 'email' => 'juan@test.com'],
];

function buscarUsuario(array $usuarios, int $id): void
{
    if (!isset($usuarios[$id])) {
        http_response_code(404);
        echo json_encode([
            'error' => true,
            'mensaje' => "Usuario con ID $id no encontrado",
        ]);
        return;
    }

    http_response_code(200);
    echo json_encode($usuarios[$id]);
}

// Probar con diferentes IDs
buscarUsuario($usuarios, 1);  // Devuelve Ana
// buscarUsuario($usuarios, 99);  // Devuelve error 404

Ejercicio 3: Validar datos de entrada

Crea una funcion que reciba datos JSON para crear un producto. Valida que tenga nombre (string no vacio) y precio (numero positivo). Devuelve error 400 si falta algo.

Ver solucion
PHP
<?php

declare(strict_types=1);

header('Content-Type: application/json');

function crearProducto(string $jsonInput): void
{
    $datos = json_decode($jsonInput, true);

    if ($datos === null) {
        http_response_code(400);
        echo json_encode(['error' => 'JSON invalido']);
        return;
    }

    $errores = [];

    // Validar nombre
    if (empty($datos['nombre']) || !is_string($datos['nombre'])) {
        $errores[] = 'El nombre es requerido y debe ser texto';
    }

    // Validar precio
    if (!isset($datos['precio']) || !is_numeric($datos['precio'])) {
        $errores[] = 'El precio es requerido y debe ser numerico';
    } elseif ((float) $datos['precio'] <= 0) {
        $errores[] = 'El precio debe ser mayor a cero';
    }

    if (!empty($errores)) {
        http_response_code(400);
        echo json_encode([
            'error' => true,
            'mensajes' => $errores,
        ]);
        return;
    }

    // Producto valido
    $producto = [
        'id' => rand(1, 1000),
        'nombre' => trim($datos['nombre']),
        'precio' => (float) $datos['precio'],
    ];

    http_response_code(201);
    echo json_encode($producto);
}

// Probar
$jsonValido = '{"nombre": "Monitor", "precio": 299.99}';
$jsonInvalido = '{"nombre": "", "precio": -10}';

crearProducto($jsonValido);

Te está gustando el curso?

Tenemos cursos premium con proyectos reales y soporte personalizado.

Descubrir cursos premium