
Compartilhar:
Sou ator formado, com uma dissertação sobre stand-up comedy, e comecei a me dedicar ao desenvolvimento em PHP por meio dos encontros da comunidade. Você pode me encontrar dando palestras e escrevendo sobre tecnologia, ou ouvindo e comprando discos curiosos da minha coleção de vinil.
Desenvolvimento rápido de APIs com Laravel e API Platform
Na opinião pessoal deste autor, mais pessoas fora do meio do PHP deveriam conhecer a API Platform. É uma ferramenta surpreendente ferramenta que pode estruturar toda a API da sua aplicação web em apenas 10 minutos para você começar a usá-la, além de oferecer uma variedade impressionante de recursos que transformarão e gerenciarão a autenticação na sua aplicação apenas alterando opções de configuração.
Neste artigo, vamos pegar uma aplicação Laravel já existente que utiliza a Messages API da Vonage e disponibilizá-la como uma API web de acordo com diversos padrões.
O que é a API Platform?
Ok, então aqui está a parte um pouco confusa: a API Platform é um framework PHP, mas esse framework, por sua vez, é implementado sobre o Symfony ou o Laravel (o que também inclui outros frameworks e plataformas que são construídos com base nessas estruturas, como o Drupal ou WinterCMS). Pense nele como um conjunto de configurações e atributos que você pode adicionar à sua modelagem de banco de dados e à pasta de configuração. Ele também vem com um painel web completo integrado, para testes com ferramentas de API, como o Postman e OpenAPI .
Inicializando uma aplicação Laravel já existente
Também conhecido como: “Aqui está um que eu fiz antes!” Vamos usar um aplicativo que possui apenas uma entidade de banco de dados: a humilde ToDo, que eu programei em um artigo anterior. Ele também usa a Messages API da Vonage para enviar o conteúdo de texto do ToDo para um dispositivo configurado quando uma das tarefas do ToDo for marcada como concluída (funcionando como uma notificação). Como se trata de um aplicativo totalmente funcional, vamos começar por inicializá-lo antes de adicionar a API Platform a ele.
Resumo: você pode encontrar o código-fonte aqui.
Pré-requisitos
git
PHP 8.3 ou superior
Node 23+ e npm
Um account da Vonage
Configurando o aplicativo web
Baixe o repositório para o seu computador: https://github.com/Vonage-Community/blog-messages_native_php
Instalar dependências:
composer installExecute as migrações na linha de comando:
php artisan migrateExecute o npm na linha de comando:
npm iNa linha de comando, execute o Vite com
npm run devNa linha de comando, execute o programa de preenchimento do banco de dados para inserir alguns dados em nosso aplicativo:
php artisan db:seedCopie o exemplo
.envpara torná-lo ativo.envna linha de comando:cp .env.example .envAdicione suas credenciais da Vonage ao
.envarquivo.
Este aplicativo usa a Messages API do Vonage para enviar um SMS quando a tarefa for concluída; portanto, você precisará criar um Account no Vonage e, em seguida, criar um aplicativo no Vonage. Ao criar o aplicativo, selecione a funcionalidade “Messages”, preencha os campos de webhooks com dados fictícios e anote o application_id na hora da criação. Mova o private.key que é baixado automaticamente para a raiz dos arquivos do seu projeto.
Para criar um aplicativo, acesse a página “Criar um aplicativo” no Painel da Vonage e defina um Nome para a sua Application.
Se você pretende usar uma API que utilize Webhooks, precisará de uma chave privada. Clique em “Gerar chave pública e privada”; o download deve iniciar automaticamente. Guarde-a em local seguro; essa chave não poderá ser baixada novamente em caso de perda. Ela seguirá a convenção de nomenclatura private_<seu ID de aplicativo>.key. Agora, essa chave pode ser usada para autenticar chamadas de API. Observação: sua chave não funcionará até que seu aplicativo seja salvo.
Escolha os recursos de que você precisa (por exemplo, Voice, Mensagens, RTC etc.) e forneça os webhooks necessários (por exemplo, URLs de eventos, URLs de resposta ou URLs de mensagens recebidas). Esses itens serão descritos no tutorial.
Para salvar e implantar, clique em “Gerar novo aplicativo” para finalizar a configuração. Seu aplicativo já está pronto para ser usado com as APIs da Vonage.
No .env arquivo, você precisará adicionar sua configuração:
VONAGE_APPLICATION_ID="<YOUR_APPLICATION_ID_HERE>"
VONAGE_PRIVATE_KEY_PATH="./private.key"
VONAGE_TO="<YOUR-NUMBER-HERE>"
Observe que VONAGE_PRIVATE_KEY_PATH deve sempre ter o valor indicado acima, pois o aplicativo irá ler sua chave privada no nível raiz.
VONAGE_TO é o número para o qual você deseja que a notificação por SMS seja enviada.
Você precisará hospedar seu aplicativo. Recomendo usar Laravel Herd. Você pode encontrar as instruções de instalação aqui. Como alternativa, você pode executar o servidor PHP embutido a partir da linha de comando: php artisan serve
App up and running!
O dilema: de MVC para API
O aplicativo foi desenvolvido como um aplicativo clássico do tipo Modelo-Visão-Controlador, com um toque de “magia” no front-end, cortesia do Laravel Livewire. No entanto, considere dois cenários:
Queremos integrar ferramentas externas ao nosso aplicativo, por isso precisaremos disponibilizar uma API.
Escalabilidade em massa significa que precisamos separar o front-end do back-end, ou seja, temos uma estrutura de JavaScript separada, como Svelte ou Vue, que recebe e envia dados para a API exposta.
A Incrível Experiência com a Plataforma de API
É hora de instalar a API Platform. Abra o terminal e digite o seguinte:
composer require api-platform/laravelAinda no terminal, conclua a instalação pelo console.
php artisan api-platform:installÉ isso aí, a instalação está concluída. Não acredita em mim? Acesse a URL do seu projeto e adicione /api:
We've certainly done -something-Temos um modelo ORM do Eloquent, Todo. Ele fica assim no aplicativo:
<?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',
];
}Você está pronto? O próximo passo vai mudar tudo, e eu vou explicar o que está acontecendo depois. Adicione 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, eu adicionei #[ApiResource]. Então, o que isso faz? Atualiza o /api/ painel:
An OpenAPI document renders our new magic APIHum, tá? Então, o que é isso, já temos um conjunto completo de rotas REST agora? Acho que devo dar uma olhada nisso. No banco de dados, temos 10 fixtures, então vamos ver o que acontece se eu usar o HTTPie para disparar a GET{id} para obter a entrada 5 (aliás: nunca exponha suas chaves primárias no banco de dados no mundo real!)
Absolute cinema!Hã? Você acabou de… criar uma API pra mim? Que tal eu enviar um PATCH solicitação para editar o título?
Suddenly, a wild REST API appearsOK. Adicionamos duas linhas de código e já temos uma API. Isso é incrível.
Aprofundando o assunto: Padrões de API e paginação
Os mais atentos entre vocês talvez tenham percebido que a API Platform adotou por padrão um padrão de estrutura de dados, sendo que a pista está nos campos chamados @context e @id. Mas por que os campos têm essa aparência?
A resposta é que a API Platform usa, por padrão, o formato JSON-LD (JSON For Linking Data). Podemos estar vendo apenas uma entidade aqui, mas se tivéssemos uma relação de entidade “um para muitos”, a API Platform trataria automaticamente os resultados retornados para você. Vamos adicionar, como exemplo, uma nova entidade chamada SubTask. No Eloquent, a relação ficaria assim:
public function subtasks(): HasMany
{
return $this->hasMany(Subtask::class);
}Chamar o mesmo endpoint geraria uma resposta como a que aparece abaixo. Lembre-se de que adicionei o código de serialização do Groups, que determina quais campos devem ser exibidos. Você pode ler sobre a serialização da API Platform aquiou, especificamente para o Laravel, usar a $visible configuração de array para definir quais partes do modelo você deseja exibir.
{
"@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
}
]
}Não é demais ter a API Platform cuidando dos seus dados de API para você? Parece que chegou a hora de se livrar de todas aquelas camadas de transformação e DTOs!
Mas, espere aí: e se o meu padrão de escolha para o desenvolvimento REST não for o JSON-LD? É aí que vamos à configuração, que você pode encontrar em 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'],
],(Deixei o aviso de direitos autorais lá só para dar ao Kevin Duglas uma menção).
Aha! Vê só, tem uma formats chave no array de configuração? Vamos alterar isso:
'formats' => [
'jsonld' => ['application/ld+json'],
'jsonhal' => ['application/hal+json'],
],Se você enviar a solicitação novamente, nada muda. Ela continua no formato JSON-LD. Por quê?
Isso faz parte da implementação da Negociação de Conteúdo da API Platform. O LD-JSON ainda é o primeira chave listada, tornando-a a padrão. No entanto, altere os cabeçalhos da sua solicitação para accept: application/hal+json e envie a solicitação:
Suddenly, a wild HAL appearsPortanto, agora o poder está nas mãos dos usuários da sua API, já que eles podem solicitar o formato que desejarem.
Isso também oferece a você, o autor da sua API, um poder incrível para criar um novo endpoint no seu aplicativo, por exemplo: /api/v2, e simplesmente alterá-lo. Vamos enlouquecer um pouco: e se a gente simplesmente quiser transformar nossa API em uma API GraphQL? Pois é. Você consegue fazer isso em apenas 3 etapas!
Instale a API Platform GraphQL com o Composer no navegador
composer require api-platform/graphqlHabilite o GraphQL no seu
configuration/api-platform.phparquivo
'graphql' => [
'enabled' => true,
'nesting_separator' => '__',
'introspection' => ['enabled' => true],
'max_query_complexity' => 500,
'max_query_depth' => 200,
// 'middleware' => null,
],Vá até
/api/graphqle o que acontece?
A Built-in GraphQL sandbox, just for youSim. É isso mesmo. Você tem um GraphQL Playground porque sua API agora é GraphQL. Se não acredita em mim:
From REST to GraphQL in mere minutesAgora você tem uma API GraphQL e uma API REST.
A paginação é uma daquelas coisas que sempre achei muito trabalhosa de implementar manualmente. A API Platform tem uma abordagem que beira o ridículo quando se trata de simplificar o processo de integração da paginação. Vamos considerar novamente nosso modelo ToDo:
<?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',
];
}Adicionei novos atributos destinados à formatação da Subtask relação. Para adicionar paginação, vou definir um valor padrão para o número de entidades retornadas por página e, em seguida, testar a page string de consulta da URL. Adicione o seguinte atributo à classe:
#[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 ModelE é isso. Pronto. Como temos 10 tarefas, isso significa que devemos ter duas páginas — 5 entidades exibidas por página. Então, você pode testar adicionar a página 2:
Magical pagination out of the boxTambém foram adicionados links de paginação — pura magia.
Conclusão
Um dos pontos que destaquei ao falar sobre o poder da API Platform na API Platform Conference 2025 foi que os desenvolvedores de PHP que usam essa estrutura diariamente provavelmente não têm noção de como esse tipo de poder é raro. Não encontrei nada mais que consiga colocar esse tipo de recurso nas mãos dos desenvolvedores e tornar tudo tão simples assim. Se você não faz parte do mundo do PHP, experimente — para mim, isso tornou o desenvolvimento de APIs divertido novamente.
Have a question or want to share what you're building?
Subscribe to the Developer Newsletter
Follow us on X (formerly Twitter) for updates
Watch tutorials on our YouTube channel
Connect with us on the Vonage Developer page on LinkedIn
Stay connected and keep up with the latest developer news, tips, and events.
Compartilhar:
Sou ator formado, com uma dissertação sobre stand-up comedy, e comecei a me dedicar ao desenvolvimento em PHP por meio dos encontros da comunidade. Você pode me encontrar dando palestras e escrevendo sobre tecnologia, ou ouvindo e comprando discos curiosos da minha coleção de vinil.