
Compartir:
Actor de formación con una disertación sobre la comedia, llegué al desarrollo de PHP a través de la escena de las reuniones. Puedes encontrarme hablando y escribiendo sobre tecnología, o tocando/comprando discos raros de mi colección de vinilos.
Desarrollo rápido de API con Laravel y API Platform
Es la opinión personal de este autor que más gente fuera del espacio PHP debe saber acerca de Plataforma API. Es una asombroso pieza de kit que puede estructurar toda su aplicación web API en 10 minutos para empezar, y viene con una vertiginosa variedad de características que va a transformar y manejar la autenticación dentro de su aplicación cambiando los interruptores de configuración.
En este artículo, tomaremos una aplicación Laravel existente que utiliza Messages API de Vonage y la abriremos como una API web bajo varios estándares.
¿Qué es una plataforma API?
Bien, esta es la parte un poco confusa: La Plataforma API es un framework PHP, pero ese framework se asienta sobre Symfony o Laravel (que también incluye otros frameworks y plataformas que se construyen sobre ellos, como por ejemplo Drupal o WinterCMS). Piense en ello como un conjunto de configuraciones y atributos que puede agregar a su modelado de base de datos y la carpeta config. También viene con un tablero web completo incorporado, para pruebas con herramientas API como Postman y OpenAPI y OpenAPI.
Arrancar una aplicación Laravel existente
AKA. "¡Aquí hay uno que hice antes!" Vamos a utilizar una aplicación que sólo tiene una entidad de base de datos: el humilde ToDo, que codifiqué en un artículo anterior. También utiliza la Mensajes API de Vonage para enviar el contenido de texto de ToDo a un dispositivo configurado cuando se marca uno de los elementos de ToDo (actuando como una notificación). Debido a que es una aplicación en pleno funcionamiento, vamos a empezar por arrancar esta aplicación antes de agregarle la Plataforma API.
TLDR; puedes encontrar el código fuente aquí.
Requisitos previos
git
PHP 8.3+
Node 23+ y npm
Una Account de Vonage
Configuración de la aplicación web
Obtenga el repositorio en su máquina: https://github.com/Vonage-Community/blog-messages_native_php
Instalar dependencias:
composer installEjecutar migraciones en la línea de comandos:
php artisan migrateEjecute npm en la línea de comandos:
npm iEn la línea de comandos, ejecute Vite con
npm run devEn la línea de comandos, ejecute el sembrador de base de datos para obtener algunos datos en nuestra aplicación:
php artisan db:seedCopie el ejemplo
.envpara convertirlo en.enven la línea de comandos:cp .env.example .envAgrega tus credenciales de Vonage al archivo
.envarchivo.
Esta aplicación utiliza la API Messages API de Vonage para enviar un SMS cuando se completa la tarea, por lo que necesitarás crear una cuenta de Vonage y luego crear una aplicación de Vonage. Al crear la aplicación, selecciona la funcionalidad Mensajes, completa los campos de webhooks con datos ficticios y anota el icono application_id al momento de la creación. Mueve el private.key que se descarga automáticamente a la raíz de los archivos de tu proyecto.
Para crear una aplicación, vaya a la sección Crear una aplicación en el panel de Vonage y define un nombre para tu aplicación.
Si tiene intención de utilizar una API que utilice Webhooks, necesitará una clave privada. Haga clic en "Generar clave pública y privada"; la descarga debería iniciarse automáticamente. Guárdela de forma segura; esta clave no puede volver a descargarse si se pierde. Seguirá la convención de nomenclatura private_<id de su aplicación>.key. Esta clave puede utilizarse ahora para autenticar llamadas a la API. Nota: La clave no funcionará hasta que se guarde la aplicación.
Elija las funciones que necesite (por ejemplo, Voice, Messages, RTC, etc.) y proporcione los webhooks necesarios (por ejemplo, URL de eventos, URL de respuestas o URL de mensajes entrantes). Estos se describirán en el tutorial.
Para guardar e implementar, haz clic en "Generar nueva aplicación" para finalizar la configuración. Tu aplicación ahora está lista para usar con las API de Vonage.
En el archivo .env tendrás que añadir tu configuración:
VONAGE_APPLICATION_ID="<YOUR_APPLICATION_ID_HERE>"
VONAGE_PRIVATE_KEY_PATH="./private.key"
VONAGE_TO="<YOUR-NUMBER-HERE>"
Tenga en cuenta que VONAGE_PRIVATE_KEY_PATH debe tener siempre el valor indicado anteriormente, ya que la aplicación resolverá la lectura de su clave privada en el nivel raíz.
VONAGE_TO es el número al que desea que se envíe la notificación por SMS.
Necesitarás servir tu aplicación. Recomiendo usar Laravel Herd. Puedes encontrar las instrucciones de instalación aquí. Alternativamente, puede ejecutar el servidor PHP integrado desde la línea de comandos: php artisan serve
App up and running!
El enigma: de MVC a API
La aplicación está escrita como una clásica aplicación Modelo-Vista-Controlador con una pizca de magia frontend cortesía de Laravel Livewire. Sin embargo, consideremos dos escenarios:
Queremos conectar herramientas externas a nuestra aplicación, por lo que necesitaremos exponer una API.
El escalado masivo significa que tenemos que desacoplar los extremos frontal y posterior, lo que significa que tenemos un marco de JavaScript independiente, como Svelte o Vue, que consume y envía datos a la API expuesta.
La increíble experiencia de la plataforma API
Es hora de instalar la Plataforma API. Abre tu terminal y añade lo siguiente:
composer require api-platform/laravelTodavía en el terminal, termina la instalación con la consola.
php artisan api-platform:installEso es todo para la instalación. ¿No me crees? Dirígete a la URL de tu proyecto y añade /api:
We've certainly done -something-Tenemos un modelo ORM de Eloquent, Todo. Se ve así en la aplicación:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Todo extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'title',
'completed',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'completed' => 'boolean',
];
}¿Estás preparado? El siguiente paso lo cambiará todo, y te explicaré lo que ocurre después. Añade este atributo:
<?php
namespace App\Models;
use ApiPlatform\Metadata\ApiResource;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
#[ApiResource]
class Todo extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'title',
'completed',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'completed' => 'boolean',
];
}OK, he añadido #[ApiResource]. ¿Y eso qué hace? Refresca el directorio /api/ dashboard:
An OpenAPI document renders our new magic APIEh, ¿vale? Entonces, ¿qué, ahora tenemos un conjunto completo de rutas REST? Supongo que debería comprobarlo. En la base de datos, tenemos 10 accesorios, así que vamos a ver qué pasa si uso HTTPie para lanzar el comando GET{id} para obtener la entrada 5 (además: ¡nunca expongas tus claves primarias en tu base de datos en el mundo real!)
Absolute cinema!¿Eh? ¿Acabas de... hacer una API para mí? ¿Qué tal si envío una PATCH solicitud para editar el título?
Suddenly, a wild REST API appearsDE ACUERDO. Hemos añadido dos líneas de código, y tenemos una API. Eso es bastante salvaje.
Profundizando: Normas API y paginación
Los más avispados se habrán dado cuenta de que la Plataforma API ha adoptado por defecto un patrón de estructura de datos, con campos denominados @contexto y @id. Pero, ¿por qué los campos tienen este aspecto?
La respuesta es que la Plataforma API utiliza por defecto el formato formato JSON-LD (JSON For Linking Data). Puede que estemos viendo sólo una entidad aquí, pero si tuviéramos una relación de entidad uno-a-muchos, la Plataforma API manejaría automáticamente los resultados devueltos por usted. Añadamos, como ejemplo, una nueva entidad llamada SubTask. En Eloquent, la relación tendría este aspecto:
public function subtasks(): HasMany
{
return $this->hasMany(Subtask::class);
}Llamando al mismo endpoint se obtendría una respuesta como la siguiente. Ten en cuenta que he añadido el código de Serialización de Grupos que determina qué campos mostrar. Puedes leer sobre la serialización de la plataforma API aquío, en el caso concreto de Laravel, utilizar la configuración de array $visible para exponer qué partes del modelo quieres renderizar.
{
"@context": "/api/contexts/Todo",
"@id": "/api/todos/5",
"@type": "Todo",
"id": 5,
"title": "sample patch request",
"completed": false,
"createdAt": "2026-03-10T13:44:23+00:00",
"updatedAt": "2026-03-11T11:41:13+00:00",
"subTasks": [
{
"@id": "/api/sub_tasks/1",
"@type": "SubTask",
"id": 1,
"title": "Write request body",
"completed": true
},
{
"@id": "/api/sub_tasks/2",
"@type": "SubTask",
"id": 2,
"title": "Send PATCH request",
"completed": false
},
{
"@id": "/api/sub_tasks/3",
"@type": "SubTask",
"id": 3,
"title": "Verify API response",
"completed": false
}
]
}¿No es genial que la Plataforma API se ocupe de los datos de tu API por ti? ¡Parece que es hora de deshacerse de todas esas capas de transformación y DTOs!
Pero, espera: ¿qué pasa si mi estándar de elección para el desarrollo REST no es JSON-LD? Es entonces cuando nos dirigimos a la configuración, que se puede encontrar en configuration/api-platform.php.
<?php
/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
use ApiPlatform\Metadata\UrlGeneratorInterface;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter;
return [
'title' => 'API Platform',
'description' => 'My awesome API',
'version' => '1.0.0',
'show_webby' => true,
'routes' => [
'domain' => null,
// Global middleware applied to every API Platform routes
// 'middleware' => [],
],
'resources' => [
app_path('Models'),
],
'formats' => [
'jsonld' => ['application/ld+json'],
// 'jsonapi' => ['application/vnd.api+json'],
// 'csv' => ['text/csv'],
],(Dejé el Copyright ahí sólo para dar a Kevin Duglas un saludo).
¿Ves que hay una formats en el array config? Vamos a cambiar eso:
'formats' => [
'jsonld' => ['application/ld+json'],
'jsonhal' => ['application/hal+json'],
],Si vuelves a enviar la petición, nada cambia. Sigue en JSON-LD. ¿Por qué?
Esto forma parte de la implementación de la Negociación de Contenidos de la Plataforma API. LD-JSON sigue siendo el primera por defecto. Pero, cambie las cabeceras de su solicitud a accept: application/hal+json y lance la solicitud:
Suddenly, a wild HAL appearsAsí que ahora el poder está en manos de los consumidores de su API, ya que pueden solicitar el formato que deseen.
También le da a usted, el autor de su API, el tipo de poder alucinante para crear un nuevo punto final en su aplicación, por ejemplo. /api/v2, y simplemente cambiarlo. Volvámonos locos: ¿y si sólo queremos cambiar nuestra API por una GraphQL? Sí. Puedes hacerlo en sólo ¡3 pasos!
Instalar la Plataforma API GraphQL con Composer en el navegador
composer require api-platform/graphqlActive GraphQL en su
configuration/api-platform.phparchivo
'graphql' => [
'enabled' => true,
'nesting_separator' => '__',
'introspection' => ['enabled' => true],
'max_query_complexity' => 500,
'max_query_depth' => 200,
// 'middleware' => null,
],Dirígete a
/api/graphql¿y qué ocurre?
A Built-in GraphQL sandbox, just for youSí, así es. Tienes un patio de juegos GraphQL porque tu API ahora es GraphQL. Si no me crees:
From REST to GraphQL in mere minutesAhora tiene una API GraphQL y una API REST.
La paginación es una de esas cosas que siempre me ha parecido un dolor muy manual de implementar. API Platform tiene un enfoque que raya en lo ridículo cuando se trata de simplificar el proceso de integración de la paginación. Considere nuestro modelo ToDo de nuevo:
<?php
namespace App\Models;
use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Symfony\Component\Serializer\Attribute\Groups;
#[ApiResource(normalizationContext: ['groups' => ['read']])]
#[ApiProperty(property: 'title', serialize: [new Groups(['read'])])]
#[ApiProperty(property: 'completed', serialize: [new Groups(['read'])])]
class Todo extends Model
{
use HasFactory;
/**
* Get the subtasks for the todo.
*/
#[ApiProperty(readableLink: true)]
#[Groups(['read'])]
public function subtasks(): HasMany
{
return $this->hasMany(Subtask::class);
}
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'title',
'completed',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'completed' => 'boolean',
];
}He añadido nuevos atributos que son para dar formato a la Subtask relación. Para añadir la paginación, voy a establecer un valor predeterminado para el número de entidades devueltas por página, a continuación, probar el page URL cadena de consulta. Añadir el siguiente atributo a la clase:
#[ApiProperty(property: 'title', serialize: [new Groups(['read'])])]
#[ApiProperty(property: 'completed', serialize: [new Groups(['read'])])]
#[ApiResource(
normalizationContext: ['groups' => ['read']],
paginationItemsPerPage: 5,
)]
#[ApiProperty(property: 'title', serialize: [new Groups(['read'])])]
#[ApiProperty(property: 'completed', serialize: [new Groups(['read'])])]
class Todo extends ModelY ya está. Hecho. Como tenemos 10 Todos, eso significa que deberíamos tener dos páginas-5 entidades devueltas por página. Así que, puedes probar añadiendo la página 2:
Magical pagination out of the boxTambién ha añadido enlaces de paginación, magia.
Conclusión
Una de las cosas que dije cuando hablé de la potencia de la Plataforma de APIs en la Conferencia de la Plataforma de APIs 2025 fue que los desarrolladores de PHP que utilizan este framework día tras día probablemente no son conscientes de lo poco frecuente que es este tipo de potencia. No he encontrado nada más que pueda poner este tipo de funciones en manos de los desarrolladores y hacerlo tan sencillo. Si no perteneces al mundo PHP, pruébalo, ha hecho que el desarrollo de APIs vuelva a ser divertido para mí.
¿Tiene alguna pregunta o quiere compartir lo que está construyendo?
Suscríbase al Boletín para desarrolladores
Síguenos en X (antes Twitter) para estar al día
Ver tutoriales en nuestro canal de YouTube
Conéctese con nosotros en la página Vonage Developer en LinkedIn
Ayúdanos a mejorar nuestra experiencia como desarrolladores rellenando nuestro cuestionario «La voz del desarrollador»
Mantente conectado y entérate de las últimas noticias, consejos y eventos para desarrolladores.
Compartir:
Actor de formación con una disertación sobre la comedia, llegué al desarrollo de PHP a través de la escena de las reuniones. Puedes encontrarme hablando y escribiendo sobre tecnología, o tocando/comprando discos raros de mi colección de vinilos.