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 Back-End si se busca procesar peticiones AJAX recibidas desde el Front-End. Además que JSON es actualmente el idioma universal para comunicar con cualquier otro lenguaje.

Devolver un JSON

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

Supongamos que recibimos un JSON, cuyo origen puede ser una petición como la siguiente.

curl -XPOST -H "Content-type: application/json" -d '{
    "email": "juana@my.email"
}' http://localhost:8000/ejemplo.php

Para capturarlo debo realizar lo siguiente.

<?php

// Recogemos toda la información recibida
$inputJSON = file_get_contents('php://input');

// Convertimos la información cruda en un diccionario
$data = json_decode($inputJSON, true);

// Imprimimos el resultado final
echo $data['email'];

Devolviendo

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:

  1. Capturar el JSON recibido.
  2. Renderizar por cada elemento un <p>.
  3. 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');

19-1 19-2 19-3 19-4

¿Te ha gustado? Comprame un café

Comentarios

{{ comments.length }} comentarios

Nuevo comentario

Nueva replica  {{ formatEllipsisAuthor(replyComment.author) }}

Acepto la política de Protección de Datos.

Escribe el primer comentario