Trabajo con APIs en PHP. En el mundo del desarrollo web moderno, las APIs (Interfaces de Programación de Aplicaciones) se han convertido en una herramienta esencial para permitir la comunicación entre distintas aplicaciones, servicios y plataformas. Ya sea para consumir información de un servicio externo (como obtener el clima, noticias o datos financieros), o para exponer nuestros propios servicios a otras aplicaciones. Trabajar con APIs es una competencia clave para cualquier desarrollador web.
En este capítulo aprenderás:
- Cómo consumir APIs externas desde PHP, utilizando herramientas como
file_get_contents
,cURL
o bibliotecas como Guzzle. Esto te permitirá conectar tu aplicación con servicios web ya existentes, extraer información y utilizarla en tu sitio web o aplicación. - Cómo crear tu propia API RESTful usando PHP puro, sentando las bases para construir servicios que puedan ser utilizados por aplicaciones frontend (JavaScript, apps móviles, etc.), u otros sistemas que necesiten acceder a tus datos.
- Cómo implementar autenticación básica en tus APIs, una técnica fundamental para proteger tu servicio y asegurarte de que solo usuarios autorizados puedan acceder a determinadas funcionalidades o recursos.
Durante este capítulo verás tanto teoría como práctica, con ejemplos paso a paso que te permitirán:
- Enviar y recibir datos en formato JSON.
- Usar métodos HTTP como GET, POST, PUT y DELETE.
- Diseñar rutas para manejar recursos (usuarios, productos, etc.).
- Implementar controles de seguridad básicos.
Este conocimiento será especialmente útil si planeas desarrollar servicios que se comuniquen con aplicaciones frontend, sistemas móviles o incluso con otras APIs. Empecemos…
11.1 Consumir APIs externas con PHP
Una de las grandes fortalezas de PHP es su capacidad para conectarse con servicios externos a través de APIs. Esto nos permite integrar datos o funcionalidades de otras plataformas (por ejemplo, datos meteorológicos, sistemas de pago, noticias, redes sociales, etc.) en tus propias aplicaciones.
Cuando hablamos de consumir una API, nos referimos a realizar una petición HTTP a un servicio externo, obtener una respuesta (normalmente en formato JSON) y trabajar con esos datos dentro de nuestro script PHP.
PHP nos proporciona varias formas de hacer esto, entre todas ellas podemos destacar estas tres:
file_get_contents()
constream_context_create()
- La biblioteca cURL
- Bibliotecas externas como Guzzle (recomendada para proyectos más grandes)
– Método: file_get_contents()
(Método sencillo)
Este método es útil para peticiones simples GET. Se puede combinar con json_decode()
para trabajar con la respuesta JSON.
Veamos como obtener datos del precio del Bitcoin desde una API pública
<?php
$url = "https://api.coindesk.com/v1/bpi/currentprice.json";
$response = file_get_contents($url);
if ($response !== false) {
$data = json_decode($response, true);
echo "El precio del Bitcoin en USD es: " . $data['bpi']['USD']['rate'] . " USD";
} else {
echo "No se pudo obtener la información.";
}
?>
Explicación:
file_get_contents()
accede a la URL y descarga el contenido que está en formato JSON.json_decode()
transforma el JSON en un array asociativo de PHP.- Accedemos a las claves del array para mostrar el valor deseado.
@TIP: Ten en cuenta que algunos servidores file_get_contents()
no permite acceder a URLs externas si allow_url_fopen
está deshabilitado en php.ini
.
– Método cURL
cURL es una herramienta más versátil para trabajar con peticiones HTTP. Te permite usar cualquier método (GET, POST, PUT, DELETE), enviar cabeceras, autenticación, etc.
Para obtener datos del clima usando la API de OpenWeatherMap podríamos hacerlo así:
<?php
$apiKey = "tu_api_key";
$city = "Madrid";
$url = "https://api.openweathermap.org/data/2.5/weather?q=$city&appid=$apiKey&units=metric";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
if ($response !== false) {
$data = json_decode($response, true);
echo "La temperatura en $city es de " . $data['main']['temp'] . "°C";
} else {
echo "Error al conectar con la API.";
}
?>
Explicación del código:
curl_init()
: inicia una sesión cURL.curl_setopt()
: define opciones (como URL y que queremos la respuesta como string).curl_exec()
: ejecuta la petición.curl_close()
: cierra la sesión.json_decode()
: convierte la respuesta JSON a array.
Este método es ideal cuando necesitas enviar parámetros por POST
, enviar cabeceras, tokens, autenticaciones, etc.
– Utilizando la biblioteca Guzzle
La tercera alternativa es utilizar la librería Guzzle que implementa un cliente HTTP para PHP muy usado en frameworks como Laravel y Symfony. Permite escribir peticiones limpias, reutilizables y fáciles de testear.
Para poder utilizar Guzzle necesitamos realiar préviamente su isntalación. Veamos como podemos hacerlo.
Instalación (con Composer)
composer require guzzlehttp/guzzle
Una vez instalada, veamos un ejemplo para obtener información de usuarios de JSONPlaceholder
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client();
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users/1');
if ($response->getStatusCode() == 200) {
$data = json_decode($response->getBody(), true);
echo "Nombre del usuario: " . $data['name'];
} else {
echo "Error al obtener los datos.";
}
?>
¿Qué ventajas nos aporta Guzzle?
- Manejo de errores y excepciones.
- Reintentos automáticos, middlewares, configuración avanzada.
- Ideal para APIs complejas.
Consideraciones de seguridad al consumir APIs
Cuando se trabaja con APIs es fundamentalr seguir ciertos criterios de seguridad como:
- Validar siempre la respuesta: Asegúrate de que recibes un código de estado HTTP 200 antes de procesar los datos.
- Manejo de errores: Usa bloques
try/catch
si estás trabajando con Guzzle ocurl_errno()
en cURL. - Protege tus claves API: No las incluyas directamente en el código en producción, mejor usa variables de entorno.
- Sanitiza los datos recibidos: Aunque vienen de una API confiable, nunca confíes completamente en los datos externos.
11.2 Crear tu propia API REST usando PHP
Como ya hemnos adelantado, una API REST (Representational State Transfer) es un conjunto de reglas que permite a diferentes aplicaciones comunicarse entre sí a través de peticiones HTTP. Las API REST son uno de los estándares más utilizados en el desarrollo web permitiendo a aplicaciones frontend (como páginas web o apps móviles) interactuar con un backend que expone datos y funcionalidades.
PHP, aunque tradicionalmente se ha usado para generar HTML dinámico, también puede usarse para crear APIs RESTful desde cero, sin necesidad de usar frameworks (como Laravel o Slim), aunque también se pueden utilizar para proyectos más complejos.
¿Cómo funciona una API REST?
Una API REST trabaja usando los métodos HTTP estándar para realizar las operaciones CRUD sobre un recurso (por ejemplo, usuarios, productos, pedidos):
Operación | Método HTTP | Descripción |
---|---|---|
Crear | POST | Agregar un nuevo recurso |
Leer | GET | Obtener uno o varios recursos |
Actualizar | PUT / PATCH | Modificar un recurso existente |
Eliminar | DELETE | Eliminar un recurso existente |
En PHP, podemos detectar el tipo de método HTTP con $_SERVER['REQUEST_METHOD']
y actuar en consecuencia.
Estructura básica de una API REST en PHP
Vamos a simular una API de productos sin utilizar frameworks, solo con PHP plano.
Supongamos que tenemos esta estructura de archivos:
api/
├── productos.php
└── data/
└── productos.json
productos.json
(Creemos una tabla de datos)
[
{ "id": 1, "nombre": "Teclado", "precio": 25.5 },
{ "id": 2, "nombre": "Ratón", "precio": 15.0 }
]
productos.php
<?php
header("Content-Type: application/json");
$archivo = __DIR__ . "/data/productos.json";
$productos = json_decode(file_get_contents($archivo), true);
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
echo json_encode($productos);
break;
case 'POST':
$nuevoProducto = json_decode(file_get_contents("php://input"), true);
$nuevoProducto['id'] = end($productos)['id'] + 1;
$productos[] = $nuevoProducto;
file_put_contents($archivo, json_encode($productos, JSON_PRETTY_PRINT));
echo json_encode(["mensaje" => "Producto añadido", "producto" => $nuevoProducto]);
break;
case 'PUT':
$datos = json_decode(file_get_contents("php://input"), true);
foreach ($productos as &$producto) {
if ($producto['id'] == $datos['id']) {
$producto['nombre'] = $datos['nombre'];
$producto['precio'] = $datos['precio'];
break;
}
}
file_put_contents($archivo, json_encode($productos, JSON_PRETTY_PRINT));
echo json_encode(["mensaje" => "Producto actualizado"]);
break;
case 'DELETE':
$datos = json_decode(file_get_contents("php://input"), true);
$productos = array_filter($productos, fn($p) => $p['id'] != $datos['id']);
file_put_contents($archivo, json_encode(array_values($productos), JSON_PRETTY_PRINT));
echo json_encode(["mensaje" => "Producto eliminado"]);
break;
default:
http_response_code(405);
echo json_encode(["error" => "Método no permitido"]);
}
?>
Una vez creado el Api, podemos invocarlo como hemos visto en el apartado anterior por algunos de los métodos que vismos, o bien desde terminal, o desde la herramienta de consultas de APIs Postman. Vamos a utilizar el terminal:
- Obtener productos (GET)
curl http://localhost/api/productos.php
- Añadir producto (POST)
curl -X POST -H "Content-Type: application/json" -d '{"nombre":"Monitor","precio":120}' http://localhost/api/productos.php
- Actualizar producto (PUT)
curl -X PUT -H "Content-Type: application/json" -d '{"id":2,"nombre":"Ratón óptico","precio":18}' http://localhost/api/productos.php
- Eliminar producto (DELETE)
curl -X DELETE -H "Content-Type: application/json" -d '{"id":1}' http://localhost/api/productos.php
Recuerda tener en cuent a las buenas prácticas a la hora de crear una API
- Validar y sanear los datos: No confíes en lo que viene del cliente.
- Devolver siempre respuestas en JSON: Y establecer
Content-Type: application/json
. - Asignar códigos HTTP adecuados:
200 OK
,201 Created
,400 Bad Request
,404 Not Found
,405 Method Not Allowed
, etc.
- Evitar exponer rutas sensibles o archivos internos.
- Controlar los errores y devolver mensajes informativos.
Recomendación: Separar lógica por controladores
En una aplicación real, no se debería manejar toda la lógica en un solo archivo. Es recomendable estructurar la API por carpetas, esto hace que la API sea más mantenible y limpia.
api/
├── controllers/
│ └── ProductoController.php
├── models/
│ └── Producto.php
└── index.php
11.3 Autenticación Básica en APIs
Cuando se desarrolla una API, uno de los aspectos más importantes es la seguridad. A diferencia de una página web tradicional donde el usuario interactúa directamente con la interfaz, las APIs exponen recursos y datos a través de peticiones HTTP, por lo que es crucial asegurarse de que solo usuarios o sistemas autorizados puedan acceder o modificar dicha información.
Una de las formas más simples de proteger una API es usando Autenticación Básica (Basic Authentication), pero hay otros tipos de autenticación para Apis como la autenticación basada en token, la autenticación con clave API y OAuth 2.0. pero estos nos los abordaremos en este capítulo.
¿Qué es la Autenticación Básica?
La autenticación básica HTTP es un método simple en el cual el cliente debe enviar un usuario y contraseña codificados en Base64 con cada solicitud HTTP.
El formato del encabezado (header) HTTP es el siguiente:
Authorization: Basic <base64(usuario:contraseña)>
Ejemplo:
Para el usuario admin
y la contraseña 1234
, la cadena base64 sería:
admin:1234 → YWRtaW46MTIzNA==
Entonces el header sería:
Authorization: Basic YWRtaW46MTIzNA==
Implementar Autenticación Básica en PHP
Para proteger una API con autenticación básica usando PHP deberemos controlar que la petición y las credenciales son correctas. Veámoslo con un un ejemplo práctico
api_protegida.php
<?php
header("Content-Type: application/json");
$usuario_valido = "admin";
$password_valido = "1234";
// Comprobar si las credenciales están presentes
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) {
header('WWW-Authenticate: Basic realm="API Privada"');
http_response_code(401);
echo json_encode(["error" => "Autenticación requerida"]);
exit;
}
// Validar las credenciales
if ($_SERVER['PHP_AUTH_USER'] !== $usuario_valido || $_SERVER['PHP_AUTH_PW'] !== $password_valido) {
http_response_code(403);
echo json_encode(["error" => "Credenciales inválidas"]);
exit;
}
// Si todo es correcto, devolver contenido de la API
echo json_encode([
"mensaje" => "Acceso autorizado",
"datos" => [
["id" => 1, "producto" => "Teclado", "precio" => 25],
["id" => 2, "producto" => "Ratón", "precio" => 15]
]
]);
?>
Ahora que ya está creadoa, puedes hacer peticiones para ver que funciona correctamente. Si lo hacemos con curl, el propio curl se encarga de codificar en base64 el usuario y password, pero para ello tenemos que hacer uso de la opción -u <user>:<pass>
Desde consola:
curl -u admin:1234 http://localhost/api_protegida.php
Limitaciones de la Autenticación Básica
Aunque fácil de implementar, la autenticación básica tiene limitaciones importantes:
- Las credenciales se envían con cada petición → hay riesgo si no se usa HTTPS.
- No hay gestión de sesiones o tokens, lo que dificulta controlar el tiempo de expiración, revocación, etc.
- No es adecuada para aplicaciones públicas o con múltiples usuarios.
Alternativas a la Autenticación Básica
Como ya te he avanzado, para crear APIs más seguras y robustas, existen métodos de autenticación más avanzados como:
- Token JWT (JSON Web Tokens).
- OAuth2.
- API Keys personalizadas.
- Autenticación por sesión + tokens CSRF (para SPAs).
Resumendio, la autenticación básica en APIs es una técnica sencilla para proyectos pequeños, APIs internas o pruebas rápidas y permite proteger endpoints restringidos sin necesidad de estructuras complejas. Sin embargo, para aplicaciones en producción o abiertas a usuarios externos, se recomienda usar mecanismos más seguros y escalables como JWT u OAuth2.
Resumen del Capítulo
En este capítulo hemos abordado la forma en la que PHP trabaja con APIs. Comenzamos explicando qué es una API, su utilidad y su papel fundamental en la comunicación entre aplicaciones. Como las APIs permiten exponer o consumir funcionalidades y datos de forma estructurada y segura mediante protocolos como HTTP, siendo REST uno de los más populares.
Aprendimos cómo usar PHP para consumir servicios externos (por ejemplo, datos de clima, usuarios, criptomonedas, etc.) a través de funciones como file_get_contents()
o herramientas más potentes como cURL
. Se mostraron ejemplos reales de cómo enviar peticiones GET
, analizar respuestas en formato JSON y trabajar con esa información dentro de una aplicación PHP.
Hemos creado nuestrea propia API RESTful básica desde cero utilizando solo PHP puro. Vimos cómo gestionar distintos tipos de peticiones (GET
, POST
, PUT
, DELETE
), cómo enviar y recibir datos en formato JSON, y cómo organizar las respuestas.
Finalmente, abordamos cómo proteger el acceso a una API mediante autenticación básica HTTP. Aprendimos a verificar usuario y contraseña codificados en base64 enviados a través de los headers de la petición. También se discutieron las limitaciones de este método y se introdujeron alternativas más robustas para entornos más complejos, como JWT u OAuth2.
Pasemos a ver unos ejercicios prácticos.
Ejercicio 1: Consumir una API externa de usuarios
Enunciado:
Utiliza PHP para consumir la API pública https://jsonplaceholder.typicode.com/users
. Muestra por pantalla una lista con el nombre, email y ciudad de cada usuario.
Enunciado:
Utiliza PHP para consumir la API pública
https://jsonplaceholder.typicode.com/users
. Muestra por pantalla una lista con el nombre, email y ciudad de cada usuario.Código:
<?php
// URL de la API externa
$url = "https://jsonplaceholder.typicode.com/users";
// Obtener el contenido de la API
$respuesta = file_get_contents($url);
// Convertir JSON en array asociativo
$usuarios = json_decode($respuesta, true);
// Mostrar los datos
echo "<h2>Lista de Usuarios</h2>";
foreach ($usuarios as $usuario) {
echo "<p><strong>Nombre:</strong> {$usuario['name']}<br>";
echo "<strong>Email:</strong> {$usuario['email']}<br>";
echo "<strong>Ciudad:</strong> {$usuario['address']['city']}</p><hr>";
}
?>
Explicación:
- Se usa
file_get_contents()
para hacer una solicitudGET
a la API. json_decode()
convierte la respuesta JSON en un array PHP.- Se recorre el array de usuarios y se extraen campos específicos.
- Se imprime el contenido en HTML.
Ejercicio 2: Crear una API REST básica en PHP (GET y POST)
Enunciado:
Crea un archivo PHP que simule una API REST con dos funcionalidades:
Si se recibe una petición GET
, devuelve una lista de productos.
Si se recibe una petición POST
, agrega un nuevo producto a un archivo JSON.
Enunciado:
Crea un archivo PHP que simule una API REST con dos funcionalidades:
Si se recibe una petición
GET
, devuelve una lista de productos.Si se recibe una petición
POST
, agrega un nuevo producto a un archivo JSON.Código:
<?php
header("Content-Type: application/json");
// Ruta al archivo de datos
$archivo = "productos.json";
// Leer productos existentes
$productos = file_exists($archivo) ? json_decode(file_get_contents($archivo), true) : [];
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
echo json_encode($productos);
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$datos = json_decode(file_get_contents("php://input"), true);
if (isset($datos['nombre']) && isset($datos['precio'])) {
$productos[] = $datos;
file_put_contents($archivo, json_encode($productos, JSON_PRETTY_PRINT));
echo json_encode(["mensaje" => "Producto agregado exitosamente"]);
} else {
http_response_code(400);
echo json_encode(["error" => "Faltan datos del producto"]);
}
}
?>
Explicación:
- Se diferencia el tipo de petición con
$_SERVER['REQUEST_METHOD']
. - Para
GET
, se devuelven los datos actuales del archivoproductos.json
. - Para
POST
, se lee la entrada JSON, se añade al array y se vuelve a guardar. - Se maneja la validación básica para evitar errores de datos faltantes.
Ejercicio 3: Proteger una API con autenticación básica
Enunciado:
Crea una API que solo permita el acceso si el usuario y contraseña proporcionados en la cabecera son correctos (admin:1234
). Si no se proporciona autenticación o es incorrecta, devuelve un error 401.
Enunciado:
Crea una API que solo permita el acceso si el usuario y contraseña proporcionados en la cabecera son correctos (
admin:1234
). Si no se proporciona autenticación o es incorrecta, devuelve un error 401.Código:
<?php
header("Content-Type: application/json");
// Autenticación Básica
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) {
header('WWW-Authenticate: Basic realm="Zona protegida"');
http_response_code(401);
echo json_encode(["error" => "Autenticación requerida"]);
exit;
}
$usuario = $_SERVER['PHP_AUTH_USER'];
$contrasena = $_SERVER['PHP_AUTH_PW'];
// Validación de credenciales
if ($usuario !== 'admin' || $contrasena !== '1234') {
http_response_code(401);
echo json_encode(["error" => "Credenciales incorrectas"]);
exit;
}
// Si la autenticación es correcta, se devuelve contenido protegido
echo json_encode(["mensaje" => "Acceso concedido", "usuario" => $usuario]);
?>
Explicación:
- Se utiliza
$_SERVER['PHP_AUTH_USER']
yPHP_AUTH_PW
para capturar usuario y contraseña. - Si no están definidos, se pide autenticación mediante el header
WWW-Authenticate
. - Si las credenciales no coinciden con
admin:1234
, se deniega el acceso con código 401. - En caso de autenticación exitosa, se muestra un mensaje de acceso concedido.
Bibliografía de programación en PHP.
- Aprende PHP desde Cero: Todo lo que necesitas para programar en PHP. Autor: Gerardo G. Urtiaga (Editorial: Editorior Independiente)
- PHP y MySQL: Domine el desarrollo de un sitio web dinámico e interactivo. Autor: Olivier Heurtel (Editorial: Ediciones ENI)
- PHP 8: Programación de aplicaciones web en el servidor: Guía paso a paso con ejemplos y proyectos prácticos. Autor: Jose Vicente Cerratlá.