Accediendo a datos de una API con PHP

Siguiendo con las recetas sencillas, en esta ocasión vamos a aprovechar el código generado en las anteriores entradas en las que con Django Rest Framework, generamos una api de autenticación con JWT.

Vamos, como decía, a reaprovechar el código para usar las capacidades de autenticación de la aplicación para crear una API con información de películas, a la que accederemos en esta ocasión con PHP.

Manos a la obra

Antes de nada, descargamos e instalamos el código del proyecto anterior. Una vez funcionando, vamos a hacer un pequeño cambio, que si bien no es fundamental para esta aplicación, si que de da un poco más de entidad.

Vamos a cambiar la configuración de la base de datos, para que deje de usar SQLite3 y pase a usar MySQL. Se trata simplemente de cambiar la configuración de la llamada a la base de datos, cambiando

# PARA TRABAJAR CON SQLITE3
DATABASES = {
     'default': {
         'ENGINE': 'django.db.backends.sqlite3',
         'NAME': BASE_DIR / 'db.sqlite3',
     }
 }

por la configuración para MySQL,

DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'demo_app',
            'USER': '__USUARIOMYSQL__',
            'PASSWORD': '__PASSMYSQL__',
            'HOST': 'localhost',
            'PORT': '3306',
        }
    }

Hemos de tener en cuenta que para poder usar MySQL como gestor de base de datos, hemos de instalar el cliente mysql de Django

pip install mysqlclient

Una vez hechas las migraciones necesarias y teniendo corriendo el proyecto, vamos a crear una aplicación que llamaremos movies, para gestionar las películas

django-admin startapp movies

Ahora crearemos un modelo sencillo, para poder almacenar películas. Algo muy simple para poder guardar 4 o 5 campos.

from django.db import models

class Movie(models.Model):
    title_movie = models.CharField(max_length=50)
    gender_movie = models.CharField(max_length=50)
    year_movie = models.CharField(max_length=50)
    director_movie = models.CharField(max_length=50)

    def __str__(self):
        return self.title_movie

Una vez hechas de nuevo las migraciones pertinenetes, tenemos ya disponible la tabla en nuestra BD

Ahora llega el momento de llenar la tabla, para tener cierta información y poder gestionarla, obviamente.

Como tengo poca imaginación, una buena herramienta para crear datos de prueba es Mockaroo, que nos permite crear tablas con datos ficticios sobre cualquier tema que queramos y con mucha consistencia, simplemente introduciendo el nombre y tipo de campo y generando la salida de los datos en el formato que necesitemos.

Generando de esta manera, tantos registros como necesitemos.

Una vez cargados estos datos en nuestra tabla

Llega el momento de generar los ficheros necesarios en nuestro proyecto: el serializer.py, views.py y urls.py de la aplicación movies.

Vamos a generar una configuración por defecto muy sencilla, con la única salvedad de que las vistas estarán protegidas para poder usarse solamente si el usuario se ha validado previamente. Vamos a ver los ficheros

## serializer.py

from rest_framework import serializers
from .models import Movie

class MovieSerializer(serializers.ModelSerializer):
    class Meta:
        model = Movie
        fields = '__all__'
# views.py

from rest_framework import generics
from .models import Movie
from .serializer import MovieSerializer
from rest_framework.permissions import IsAuthenticated

# Clase para ver todas las películas
class MovieList(generics.ListCreateAPIView):
    queryset = Movie.objects.all()
    serializer_class = MovieSerializer
    permission_classes = [IsAuthenticated]

# Clase para ver una pelicula concreta
class MovieDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Movie.objects.all()
    serializer_class = MovieSerializer
    permission_classes = [IsAuthenticated]
# urls.py (movies)

from django.urls import path
from . import views

urlpatterns = [
    path('movies/', views.MovieList.as_view(), name='movie-list'),
    path('movies/<int:pk>/', views.MovieDetail.as_view(), name='movie-detail'),
]

Finalmente añadimos la referencia a movies detro del fichero urls.py general del proyecto

from django.contrib import admin
from django.urls import path,include
# importamos simplejwt
from rest_framework_simplejwt import views as jwt_views


urlpatterns = [
    path('admin/', admin.site.urls),
    # URLS DE VALIDACION DEL TOKEN
    #path('api/token/', jwt_views.TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', jwt_views.TokenRefreshView.as_view(), name='token_refresh'),
    path('users/', include('users.urls')),
    path('movies/', include('movies.urls')),
    
]

En este momento, ya podemos arrancar nuestro proyecto y comprobar mediante Postman que la configuración y acceso a través de la autenticación es correcto.

Primero comprobamos que no podemos acceder sin validarnos

Ahora, nos validamos para obtener los token de acceso y refresh

Y usamos esos mismos token para acceder a la API de películas, esta vez validados

Como vemos, la autenticación y la vista están funcionando correctamente y nos muestra la información de las películas que tenemos almacenadas.

Usando PHP para acceder a la API

Ahora que hemos comprobado que funciona correctamente el acceso y la autenticación, y podemos ver la información de la API, vamos a generar un pequeño script en PHP que nos permitirá validadarnos y mostrar la información por pantalla, de momento, en formato JSON.

Vamos a dividir el script en dos partes, un fichero config.php, con las variables necesarias y otro fichero ver_peliculas.php, con la conexión y la respuesta. Vamos a ello.

<?php
// config.php

// Configuración de variables de entorno

// URL de autenticación
$auth_url_dest = "http://127.0.0.1:8000/users/token/"; 

// URL de la API de peliculas
$api_url_dest = "http://127.0.0.1:8000/movies/movies/"; 

// Credenciales de la API
$api_username = "__USUARIO_API__";
$api_password = "__PASSWORD_API__";

?>
<?php
// ver_peliculas.php
include 'config.php';

// URL de autenticación
$auth_url = $auth_url_dest; 

// Datos para la solicitud de autenticación
$auth_data = array(
    'username' => $api_username,
    'password' => $api_password
);

// Llamamos a la API de autenticación
$options = array(
    'http' => array(
        'method'  => 'POST',
        'header'  => 'Content-Type: application/x-www-form-urlencoded',
        'content' => http_build_query($auth_data)
    )
);

$context  = stream_context_create($options);
$response = file_get_contents($auth_url, false, $context);

if ($response === FALSE) {
    die('Error al realizar la solicitud de autenticación');
}

// La variable $response ahora contiene el token de acceso.
$auth_response = json_decode($response, true);

if (isset($auth_response['access'])) {
    $access_token = $auth_response['access'];
    $refresh_token = $auth_response['refresh'];

    // URL de la API de peliculas, si está la autenticación OK
    $api_url =  $api_url_dest; 

    // Token de acceso y el refresh token en el contenido
    $options = array(
        'http' => array(
            'header' => "Authorization: Bearer $access_token",
        )
    );

    $context  = stream_context_create($options);
    $response = file_get_contents($api_url, false, $context);

    if ($response === FALSE) {
        die('Error al realizar la solicitud a la API de peliculas');
    }

    // Respuesta de la API de peliculas en formato JSON.
    echo $response;
} else {
    die('No se pudo obtener el token de acceso.');
}

?>

Una vez configurados los ficheros, los almacenamos en una carpeta de la raíz de nuestro servidor web, en mi caso Apache, corriendo en Ubuntu, teniendo en cuenta que el interprete de PHP debe estar instalado y corriendo correctamente.

Finalmente, solo será necesario llamar al fichero ver_peliculas.php desde el navegador, para que nos devuelva el JSON (si ha ido todo bien) con el listado de películas.

Y listo, aquí tenemos el listado de películas, correctamente cargado para hacer lo que necesitemos con ellas. En mi caso, estoy usando un plugin de Chrome llamado Json-viewer, que me permite formatear más amigablemente los json.

En próximos post, accederemos a esta información con otros medios como Vue.js o JQuery, para ver diferentes formas de recoger los datos de una API.

Espero que os haya resultado interesante.

Por Jose Manuel Sanz Prieto

Desarrollador web. En este blog hablo de fotografía, programación con Django, Python, PHP y privacidad.

1 comentario

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *