Lección 19: API
Un API es un sistema de comunicación entre lenguajes o equipos. Nos ayudará a recibir JSONs y a generar respuesta filtrando por verbos y enviando cabeceras especiales.
Es esencial en todo backend si se busca procesar peticiones AJAX recibidas desde el frontend. Además que JSON es actualmente el idioma universal para comunicar con cualquier otro lenguaje.
Servir un JSON como un API
Veamos un ejemplo sencillo donde devolvemos un JSON a partir de un diccionario.
<?php
// Información
$relojes = [
[
'marca' => 'Marea',
'origen' => 'Spain'
],
[
'marca' => 'Rolex',
'origen' => 'Suiza'
],
[
'marca' => 'Omega',
'origen' => 'Suiza'
],
[
'marca' => 'Casio',
'origen' => 'Japón'
]
];
// Cabecera que indica el tipo de contenido a servir
header('Content-Type: application/json');
// Convirte a JSON y lo imprime
echo json_encode($relojes);
Generando un contenido ideal para alimentar a JavaScript u otros lenguajes.
[
{
"marca": "Marea",
"origen": "Spain"
},
{
"marca": "Rolex",
"origen": "Suiza"
},
{
"marca": "Omega",
"origen": "Suiza"
},
{
"marca": "Casio",
"origen": "Japón"
}
]
Recoger un JSON de un API
Para obtener el JSON debemos utilizando un cliente HTTP que gestione las cabeceras, verbos y demás elementos técnicos. Dentro del ecosistema PHP es altamente estandarizado invocar a curl
. en otras palabras, dejar la responsabilidad fuera del código. En la gran mayoría de las configuraciones de PHP se habilita la extensión que nos permite ejecutarlo.
A continuación puede observar una función de ejemplo que puede ser de ayuda:
/**
* Obtiene un JSON de una url
* @param {string} $url
* @param {string} $method - Por defecto GET.
* @param {array} $body - Diccionario con elementos a enviar. Por defecto [].
* @return {array}
*/
function getJSON(string $url, string $method = 'GET', array $body = []): array {
$curl = curl_init();
$json = json_encode($body);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($curl, CURLOPT_POSTFIELDS, $json);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($json))
);
$result = curl_exec($curl);
curl_close($curl);
return json_decode($result, $assoc = true) ;
}
Aquí puede ver otro ejemplo donde se llama.
$data = getJSON('https://dominio.com/api/v1/dinosaurios/', 'POST', array('email' => 'juana@my.email'));
Control de método
En algun momento habrá que vigilar que método estamos recibiendo (GET
, POST
, PUT
, DELETE
, etc). Y en caso contrario devolver un código de error apropiado.
<?php
// Filtramos por el método POST
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// Cabecera que indica el tipo de contenido a servir
header('Content-Type: application/json');
// Indicamos en la cabecera que tipo de métodos están disponibles
header("Access-Control-Allow-Methods: POST, OPTIONS");
// Indicamos el código que devolveremos. 200 en caso que todo sea correcto.
http_response_code(200);
// Imprimimos un JSON de respuesta con el código 200
echo json_encode([
'status' => 'ok'
]);
} else {
// Indicamos el código que devolveremos. 405: método no permitido
http_response_code(405);
// Imprimimos un JSON de respuesta.
echo json_encode([
'status' => 'ok'
]);
}
Ejemplo formulario de contacto
Usando lo aprendido en la lección E-mails, veamos como podemos crear un API que facilite el envío asíncrono de un formulario de contacto. Un problema muy común donde muchos desarrollares acaban utilizando un servicio por desconocimiento.
Enviaremos la siguiente petición.
curl -XPOST -H "Content-type: application/json" -d '{
"nombre": "Juana",
"apelldios": "De Arco",
"email": "juana@my.email",
"nacionalidad": "francia",
"mensaje": "¡Libertad!"
}' http://localhost:8000/api-contacto.php
El API se encargará de:
- Capturar el JSON recibido.
- Renderizar por cada elemento un
<p>
. - Enviar un correo con el HTML generado a un servidor SMTP en concreto.
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
require_once('vendor/autoload.php');
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
function getJSON() {
$inputJSON = file_get_contents('php://input');
return json_decode($inputJSON, true);
}
function getHTMLMessage($data) {
return array_reduce(array_keys($data), function ($carry, $key) use ($data) {
$carry .= "<p><strong>$key:</strong> $data[$key]</p>";
return $carry;
});
}
function responseJSON($data, $code=200) {
header('Content-Type: application/json');
header("Access-Control-Allow-Methods: POST, OPTIONS");
http_response_code($code);
echo json_encode($data);
}
// Crea objeto
$mail = new PHPMailer();
try {
// Configuración servidor SMTP
$mail->isSMTP();
$mail->Host = 'smtp.correo.com';
$mail->SMTPAuth = true;
$mail->Username = 'usuario@correo.com';
$mail->Password = 'contraseña';
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->setFrom('emisor@correo.es', 'Nombre emisor');
// Quien lo recibe
$mail->addAddress('receptor@correo.es', 'Nombre receptor');
// Contenido
$mail->isHTML(true);
$mail->Subject = 'Mi asunto';
$mail->Body = getHTMLMessage(getJSON());
// Enviar
$mail->send();
} catch (Exception $e) {
responseJSON([
'status' => 'ko'
], 500);
}
// Respuesta correcta con el código 200
responseJSON([
'status' => 'ok'
]);
} else {
// Respuesta de error con el código 405
responseJSON([
'status' => 'ko'
], 405);
}
Estructura de rutas
Antes de realizar tu API debes dar una estructura lógica para que los desarrolladores asimilen rápidamente como hacer llamadas. En la siguiente tabla puedes ver un ejemplo de una supuesta biblioteca con rutas usando un formato ampliamente extendido llamado API REST.
Ruta | Método | Funcionalidad |
---|---|---|
/signup | POST | Registro |
/auth/login | POST | Inicio de sesión |
/auth/logout | GET | Cerrar sesión |
/biblioteca | GET | Lista todas las bibliotecas |
/biblioteca | POST | Crea una nueva biblioteca |
/biblioteca/45 | GET | Obtiene la biblioteca |
/biblioteca/45 | PUT | Actualiza la biblioteca |
/biblioteca/45 | DELETE | Borra la biblioteca |
/biblioteca/45/libros | GET | Lista todos los libros de la biblioteca |
/biblioteca/45/libros/21 | GET | Obtiene el libro de la biblioteca |
/biblioteca/45/libros/21 | PUT | Actualiza el libro de la biblioteca |
/biblioteca/45/libros/21 | DELETE | Borra el libro de la biblioteca |
Cabeceras interesantes
Enviar contenido JSON
header('Content-Type: application/json');
Habilitar CORS
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
Indicar caché
Medida en segundos. Ejemplo de un día.
header('Access-Control-Max-Age: 86400');
Métodos disponibles
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
Esta obra está bajo una Licencia Creative Commons Atribución-NoComercial-SinDerivadas 4.0 Internacional.
¿Me invitas a un café? ☕
Puedes hacerlo usando el terminal.
ssh customer@andros.dev -p 5555
Comentarios
Nuevo comentario
Nueva replica {{ formatEllipsisAuthor(replyComment.author) }}
Escribe el primer comentario
{{ comments.length }} comentarios