Web API con Laravel y PHP: Parte 1
Laravel es un popular y poderoso framework de PHP, diseñado para desarrollar aplicaciones web full-stack con facilidad y rapidez, lo que nos permite concentrarnos solo en la lógica y reglas de negocio de nuestra aplicación en lugar de invertir tiempo en escribir las capas inferiores que tendremos ya solucionadas. En esta guía, exploraremos cómo crear un API desde cero con esta herramienta, para cualquier aplicación que necesites.
En esta ocasión, escribiremos un API para un blog básico en el cual habrá entradas, autores y comentarios. Manejaremos la codificación de datos en formato JSON. En esta primera parte, nos enfocaremos en la configuración inicial del API y en la creación de las primeras entradas, dejando el resto para etapas posteriores.
Instalación
Antes de comenzar, es importante contar con los siguientes paquetes de software instalados: un IDE o editor de texto (VSCode, Sublime, Vim, etc.) y Docker, con el cual instalaremos y manejaremos todas las dependencias de nuestro proyecto.
Laravel 9 posee una herramienta llamada Sail que funciona como interfaz entre el desarrollador y Docker, lo cual permitirá manipular nuestro ambiente de desarrollo de manera sencilla.
Para instalar Laravel y todas sus dependencias con Sail, primero debemos asegurarnos de que Docker está corriendo en nuestra computadora. Después, hay que ejecutar el siguiente comando en la terminal:
curl -s "https://laravel.build/api-ejemplo?with=mysql" | bash
Elegimos MySQL como el motor de base de datos que va a almacenar toda la información de nuestro API. Si prefieres, puedes sustituir “api-ejemplo” por el nombre de tu aplicación en éste y todos los comandos posteriores en esta guía.
Una vez terminada la instalación por completo, hay que navegar al nuevo directorio que contiene nuestra nueva aplicación web…
cd api-ejemplo
…y levantar nuestro proyecto:
./vendor/bin/sail up
Si hicimos todo bien, podemos visitar http://localhost/ en nuestro navegador para ver la pantalla de inicio de Laravel. Ésta garantiza que ya tenemos correctamente instalado Laravel y todas sus dependencias.
Si deseas inspeccionar o modificar las variables de configuración que Sail agrega en automático, en cualquier momento puedes encontrarlas en el archivo .env en la raíz del directorio del proyecto.
Como necesitaremos ejecutar Sail varias veces en esta guía, es recomendable que configures un alias en tu ambiente de bash. Agrega esta línea al archivo de configuración de tu ambiente de shell (usualmente .bashrc o .zshrc en tu carpeta de inicio) y reinicia la terminal:
alias sail='[ -f sail ] && sh sail || sh vendor/bin/sail'
¡Ahora sí! Estamos listos para comenzar a construir nuestro API.
Modelo
Para crear y almacenar una entrada del blog, necesitamos decirle a Laravel que tenemos la intención de guardar esta información en nuestra base de datos. Para ello crearemos un modelo, el cual es una clase de PHP que representa un objeto y todas sus propiedades que queremos almacenar y servir mediante el API.
Laravel cuenta con un motor de modelos muy poderoso llamado Eloquent, mismo que no solo nos permite definir modelos, sino también las relaciones entre ellos y cómo se traducen éstas a consultas en la base de datos. Además, cuenta con comandos que nos permiten generar modelos y otros archivos de forma automática.
Para generar nuestro primer modelo BlogPost, ejecutaremos el siguiente comando:
sail artisan make:model -m BlogPost
Esto nos va a generar dos archivos:
- app/Models/BlogPost.php
Nuestra clase BlogPost - database/migrations/2022_09_05_040815_create_blog_posts_table.php
La migración que crea la tabla blog_posts en la base de datos. El nombre de este archivo cambiará dependiendo de la fecha en la que lo hayas generado.
Primero, necesitamos especificar cuáles campos queremos guardar en nuestra tabla de entradas de blog. Para esto, navega al archivo nuevo de migración y edítalo para que quede así:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('blog_posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('blog_posts');
}
};
Con esto, agregamos las columnas de title y content que contendrán el título y contenido de la entrada de blog, respectivamente.
Para aplicar los cambios a la base de datos, ejecutemos este comando:
sail artisan migrate
Después, necesitaremos decirle a Laravel cuáles campos podremos asignar masivamente a la hora de crear nuestras entradas de blog. Modifica el archivo app/Models/BlogPost.php para que contenga lo siguiente:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class BlogPost extends Model
{
use HasFactory;
protected $fillable = ['title', 'content'];
}
Ahora, crearemos la vista que traducirá estas entradas de blog en objetos JSON para devolver en nuestro API.
Vista
Necesitamos generar un objeto que nos ayude a transformar todas las entradas de blog en objetos JSON para devolver en nuestro API cuando estén listas. Laravel denomina a estas clases como Resources. Crearemos uno para nuestra entrada de blog con este comando:
sail artisan make:resource BlogPostResource
Esto generará el archivo app/Http/Resources/BlogPostResource.php, el cual necesitamos modificar para que tenga el siguiente contenido:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class BlogPostResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'content' => $this->content,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at
];
}
}
Como se puede observar, aquí definimos cuáles son los campos de nuestras entradas de blog que queremos exponer al API mediante el método toArray. Ya con esto listo, podemos comenzar a editar nuestro controlador.
Controlador
Laravel también nos puede ayudar a generar el controlador que necesitamos para manejar todas las entradas de blog. Un controlador es una clase que maneja las reglas de negocio referentes a un modelo, por ejemplo cómo se crean, visualizan, editan, etc.
Generaremos nuestro controlador con este comando:
sail artisan make:controller BlogPostController --model=BlogPost --api
Esto generará el archivo app/Http/Controllers/BlogPostController.php el cual modificaremos para poder guardar nuevas entradas, enlistarlas, editarlas o eliminarlas.
Crear una entrada de blog
Para crear entradas, necesitamos modificar el método store en BlogPostController a que tenga lo siguiente:
public function store(Request $request)
{
$request->validate([
'title' => ['required', 'string'],
'content' => ['required', 'string']
]);
$post = BlogPost::create([
'title' => $request->get('title'),
'content' => $request->get('content')
]);
return new BlogPostResource($post);
}
Como se observa, Laravel nos ayuda a validar que los valores de title y content que nos envíen en el API sean del tipo de dato correcto. Posteriormente, usamos estos datos para crear una nuevo BlogPost y, finalmente, lo regresamos en el Resource que construimos con antelación.
Para probar que nuestro API funciona correctamente, primero necesitamos registrar el controlador hacia una ruta en nuestro API. Para hacerlo, solo basta con agregar esta línea al archivo routes/api.php:
Route::resource('blog-posts', BlogPostController::class);
Con esto, podemos ejecutar esta petición desde la consola:
curl --request POST \
--url 'http://localhost/api/blog-posts/?=' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
"title": "Hola Mundo",
"content": "Esta es mi primer entrada de blog"
}'
Si hicimos todo bien, veremos una respuesta similar a la siguiente:
{"data":{"id":1,"title":"Hola Mundo","content":"Esta es mi primer entrada de blog","created_at":"2022-09-06T03:19:51.000000Z","updated_at":"2022-09-06T03:19:51.000000Z"}}%
¡Felicidades! Ya creaste tu primera entrada de blog mediante tu nuevo API.
Consultar entradas de blog
Para consultar la entrada que acabamos de crear, necesitamos modificar el método de show en nuestro controlador para que contenga lo siguiente:
public function show(BlogPost $blogPost)
{
return new BlogPostResource($blogPost);
}
Laravel automáticamente buscará el objeto correcto basado en la ruta que hayamos enviado al API. Podemos consultar con este comando en consola:
curl --request GET \
--url 'http://localhost/api/blog-posts/1?=' \
--header 'Accept: application/json'
Recibiremos la misma respuesta que la sección anterior:
{"data":{"id":1,"title":"Hola Mundo","content":"Esta es mi primer entrada de blog","created_at":"2022-09-06T03:19:51.000000Z","updated_at":"2022-09-06T03:19:51.000000Z"}}%
También necesitaremos una forma de consultar una lista de todas las entradas que hayamos creado. Para ello, modificaremos el método index:
public function index()
{
return BlogPostResource::collection(BlogPost::all());
}
Hecho lo anterior, veremos que nos trae una lista de todas las entradas que existen hasta el momento:
curl --request GET \
--url 'http://localhost/api/blog-posts?=' \
--header 'Accept: application/json'
{"data":[{"id":1,"title":"Hola Mundo","content":"Esta es mi primer entrada de blog","created_at":"2022-09-06T03:19:51.000000Z","updated_at":"2022-09-06T03:19:51.000000Z"}]}%
Editar o eliminar entradas
Para editar una entrada, necesitamos modificar el método update de la siguiente forma:
public function update(Request $request, BlogPost $blogPost)
{
$attributes = $request->validate([
'title' => ['required', 'string'],
'content' => ['required', 'string']
]);
$blogPost->update($attributes);
return new BlogPostResource($blogPost);
}
Acto seguido, probaremos este comando en la terminal. Nota cómo usamos PUT para editar la entrada:
curl --request PUT \
--url 'http://localhost/api/blog-posts/1?=' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
"title": "Hola Mundo",
"content": "Prueba de edit"
}'
{"data":{"id":1,"title":"Hola Mundo","content":"Prueba de edit","created_at":"2022-09-06T03:19:51.000000Z","updated_at":"2022-09-06T03:19:51.000000Z"}}%
Finalmente, para eliminar la entrada modificamos destroy de la siguiente manera::
public function destroy(BlogPost $blogPost)
{
$blogPost->delete();
}
Y probamos con DELETE:
curl --request DELETE \
--url 'http://localhost/api/blog-posts/1?=' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
Conclusión
Acabamos de crear un API muy sencillo para altas, bajas y cambios de entradas de blog sencillas. Asimismo, demostramos cómo utilizar Laravel para lograr esta tarea en solo unos cuantos minutos y su poder para validar datos, manejar rutas, hacer interfaz con la base de datos, etc. Esto es sólo una muestra de la capacidad de esta herramienta para generar APIs extremadamente robustos, útiles para aplicaciones muy grandes en producción.
En la próxima parte, agregaremos usuarios mediante endpoints de registro e inicio de sesión y aprenderemos cómo manejar tokens con Laravel para garantizar la seguridad de los datos de cada uno de ellos.
Revelo Content Network da la bienvenida a todas las razas, etnias, nacionalidades, credos, géneros, orientaciones, puntos de vista e ideologías, siempre y cuando promuevan la diversidad, la equidad, la inclusión y el crecimiento profesional de los profesionales en tecnología.