Installation:
composer require api-platform/laravel
Run migrations if included in the package:
php artisan migrate
Basic Configuration:
php artisan vendor:publish --provider="ApiPlatform\Laravel\ApiPlatformServiceProvider" --tag="api-platform"
config/api-platform.php to match your API needs (e.g., enable/disable features like filters, pagination, or serialization groups).First Use Case:
#[ApiResource]:
use ApiPlatform\Metadata\ApiResource;
#[ApiResource]
class Post
{
// Model logic
}
/api/posts (or your configured route prefix).Resource Configuration:
#[ApiResource(
operations: [
new Get(),
new Post(),
new GetCollection(),
new Patch(),
new Delete(),
],
normalizationContext: ['groups' => ['post:read']],
denormalizationContext: ['groups' => ['post:write']],
)]
class Post {}
ApiResource methods (e.g., getOperations()).State Providers:
POST, PUT, or PATCH:
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
#[ApiResource(processor: MyCustomProcessor::class)]
class Post {}
class MyCustomProcessor implements ProcessorInterface
{
public function process($data, Operation $operation, array $uriVariables = [], array $context = [])
{
// Custom logic (e.g., validation, business rules)
return $data;
}
}
Filters and Pagination:
config/api-platform.php:
'collection' => [
'pagination' => ['enabled' => true, 'items_per_page' => 30],
'filters' => ['search', 'date', 'boolean'],
],
ApiFilterInterface.Serialization Groups:
#[Groups(['post:read'])]
#[ApiProperty(identifier: true)]
public ?int $id = null;
#[Groups(['post:write'])]
public ?string $title = null;
Authentication/Authorization:
#[ApiResource(
security: "is_granted('ROLE_ADMIN')",
securityMessage: 'Access denied.'
)]
class AdminPost {}
#[Security] attribute for granular control.Event Handling:
pre.extract, post.persist):
use ApiPlatform\Symfony\EventListener\EventPriorities;
public function onPostPersist(PostPersistEvent $event)
{
$post = $event->getData();
// Custom logic (e.g., logging, notifications)
}
EventSubscriber or directly in ApiPlatformServiceProvider.ApiPlatform\Bundle\Test\ApiTestCase for API tests:
public function testGetPosts(): void
{
$response = $this->get('/api/posts');
$this->assertResponseIsSuccessful();
}
#[OpenApi] attributes or api-platform/openapi package.Caching:
config/api-platform.php:
'http_cache' => [
'enabled' => false,
// or customize TTL/headers
],
php artisan api-platform:cache:clear
Route Conflicts:
#[ApiResource] routes don’t clash with Laravel’s web routes. Use route() middleware to prioritize:
Route::group(['middleware' => 'api'], function () {
// API Platform routes
});
Serialization Issues:
Post ↔ User) may cause errors. Use #[ApiProperty(serialize: false)] or implement ApiResource\Metadata\PostSerialize:
#[ApiResource]
class Post
{
#[ApiProperty(serialize: false)]
public User $author;
}
Pagination:
#[ApiFilter] or override getCollection():
#[ApiResource(getCollection: MyCustomCollection::class)]
class Post {}
Validation:
#[Assert\NotBlank]) work, but API Platform may override them. Use denormalizationContext to enforce:
#[ApiResource(
denormalizationContext: ['validation_groups' => ['default', 'post']]
)]
Database Drivers:
ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtension.Enable API Debug Toolbar:
// config/api-platform.php
'debug' => env('APP_DEBUG', false),
Log Serialization:
#[ApiResource(
serializationContext: ['groups' => ['post:read'], 'enable_max_depth' => true]
)]
Common Errors:
#[ApiResource] is annotated and routes are generated (php artisan route:list).storage/logs/laravel.log) for validation or ORM issues.fruitcake/laravel-cors) if needed.Custom Formats:
ApiPlatform\Metadata\Format:
#[ApiResource(formats: ['jsonld', 'html'])]
GraphQL:
api-platform/graphql to expose GraphQL endpoints alongside REST.Webhooks:
post.persist) using ApiPlatform\Symfony\EventListener\EventPriorities.Admin Panel:
api-platform/admin for a built-in admin interface.Testing:
ApiTestCase for reusable test logic:
class CustomApiTestCase extends ApiTestCase
{
protected function createTestPost(): Post
{
return Post::factory()->create();
}
}
How can I help you explore Laravel packages today?