API Platform Symfony REST: Hướng Dẫn Đầy Đủ và Câu Hỏi Phỏng Vấn 2026
Hướng dẫn chi tiết API Platform Symfony để xây dựng REST API hiện đại. Tìm hiểu cách cài đặt, cấu hình, thao tác CRUD và các câu hỏi phỏng vấn 2026.

API Platform là framework PHP phổ biến nhất để xây dựng API hiện đại dựa trên Symfony. Framework này cung cấp nhiều tính năng sẵn có như tài liệu OpenAPI, phân trang, lọc dữ liệu và xác thực. Bài viết này hướng dẫn cách sử dụng API Platform để xây dựng REST API có khả năng mở rộng và sẵn sàng cho production.
API Platform 4.x giới thiệu state providers và processors mới thay thế data providers cũ. Hãy đảm bảo sử dụng phiên bản mới nhất để có được tất cả các tính năng hiện đại.
Cài Đặt API Platform trong Symfony
Bước đầu tiên là cài đặt API Platform bằng Composer. Framework này tích hợp hoàn hảo với Symfony 7 và cung cấp bundle sẵn sàng sử dụng.
composer create-project symfony/skeleton my-api
cd my-api
composer require apiSau khi cài đặt, API Platform tự động cấu hình routes và tài liệu. Cấu hình cơ bản có thể được tìm thấy trong file config/packages/api_platform.yaml.
# config/packages/api_platform.yaml
api_platform:
title: 'My API'
version: '1.0.0'
formats:
jsonld: ['application/ld+json']
json: ['application/json']
defaults:
stateless: true
cache_headers:
vary: ['Content-Type', 'Authorization', 'Origin']
swagger:
versions: [3]Tạo Resource API Đầu Tiên
API Platform sử dụng PHP attributes để định nghĩa resources. Mỗi entity được đánh dấu với #[ApiResource] tự động có các endpoints CRUD.
<?php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use ApiPlatform\Metadata\Delete;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity]
#[ApiResource(
operations: [
new GetCollection(),
new Get(),
new Post(),
new Put(),
new Delete()
],
paginationItemsPerPage: 20
)]
class Product
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
#[Assert\NotBlank]
#[Assert\Length(min: 3, max: 255)]
private string $name;
#[ORM\Column(type: 'text')]
private string $description;
#[ORM\Column(type: 'decimal', precision: 10, scale: 2)]
#[Assert\Positive]
private string $price;
#[ORM\Column]
private \DateTimeImmutable $createdAt;
public function __construct()
{
$this->createdAt = new \DateTimeImmutable();
}
// Getters and setters...
}Lọc và Sắp Xếp Dữ Liệu
API Platform cung cấp nhiều bộ lọc tích hợp có thể kích hoạt dễ dàng. Bộ lọc cho phép client truy vấn dữ liệu dựa trên các tiêu chí nhất định.
<?php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Doctrine\Orm\Filter\RangeFilter;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[ApiResource]
#[ApiFilter(SearchFilter::class, properties: [
'name' => 'partial',
'description' => 'partial',
'category.name' => 'exact'
])]
#[ApiFilter(OrderFilter::class, properties: ['name', 'price', 'createdAt'])]
#[ApiFilter(RangeFilter::class, properties: ['price'])]
#[ApiFilter(DateFilter::class, properties: ['createdAt'])]
class Product
{
// Properties...
}Ví dụ truy vấn sử dụng bộ lọc:
# Tìm sản phẩm có tên chứa "laptop"
GET /api/products?name=laptop
# Lọc theo khoảng giá
GET /api/products?price[gte]=100&price[lte]=500
# Sắp xếp theo giá giảm dần
GET /api/products?order[price]=descXác Thực và Serialization Groups
Xác thực trong API Platform sử dụng Symfony Validator component. Serialization groups cho phép kiểm soát chi tiết dữ liệu được trả về.
<?php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity]
#[ApiResource(
normalizationContext: ['groups' => ['product:read']],
denormalizationContext: ['groups' => ['product:write']],
operations: [
new GetCollection(normalizationContext: ['groups' => ['product:list']]),
new Get(normalizationContext: ['groups' => ['product:read', 'product:detail']]),
new Post()
]
)]
class Product
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
#[Groups(['product:read', 'product:list'])]
private ?int $id = null;
#[ORM\Column(length: 255)]
#[Assert\NotBlank(message: 'Product name is required')]
#[Groups(['product:read', 'product:list', 'product:write'])]
private string $name;
#[ORM\Column(type: 'text')]
#[Groups(['product:read', 'product:detail', 'product:write'])]
private string $description;
#[ORM\Column(type: 'decimal', precision: 10, scale: 2)]
#[Assert\Positive(message: 'Price must be positive')]
#[Groups(['product:read', 'product:list', 'product:write'])]
private string $price;
// Getters and setters...
}State Providers và Processors
API Platform 4 giới thiệu State Providers và Processors cho custom logic. Đây là sự thay thế cho Data Providers và Data Persisters từ phiên bản trước.
<?php
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Repository\ProductRepository;
class ProductStateProvider implements ProviderInterface
{
public function __construct(
private ProductRepository $repository
) {}
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
if (isset($uriVariables['id'])) {
return $this->repository->find($uriVariables['id']);
}
return $this->repository->findActiveProducts();
}
}State Processor cho custom logic khi lưu dữ liệu:
<?php
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Mailer\MailerInterface;
class ProductProcessor implements ProcessorInterface
{
public function __construct(
private EntityManagerInterface $em,
private MailerInterface $mailer
) {}
public function process(
mixed $data,
Operation $operation,
array $uriVariables = [],
array $context = []
): mixed {
$this->em->persist($data);
$this->em->flush();
// Send notification email
$this->sendNotification($data);
return $data;
}
private function sendNotification(object $product): void
{
// Email logic...
}
}Xác Thực và Phân Quyền
API Platform tích hợp với Symfony Security cho xác thực JWT hoặc API token.
# config/packages/security.yaml
security:
firewalls:
api:
pattern: ^/api
stateless: true
jwt: ~
access_control:
- { path: ^/api/docs, roles: PUBLIC_ACCESS }
- { path: ^/api/products, roles: PUBLIC_ACCESS, methods: [GET] }
- { path: ^/api, roles: ROLE_USER }Sử dụng security ở cấp resource:
<?php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Delete;
#[ApiResource(
operations: [
new Get(),
new Post(security: "is_granted('ROLE_ADMIN')"),
new Delete(
security: "is_granted('ROLE_ADMIN') or object.owner == user",
securityMessage: "Only admin or owner can delete this resource"
)
]
)]
class Product
{
// Properties...
}Kiểm Thử API Endpoints
Kiểm thử API rất quan trọng để đảm bảo các endpoints hoạt động chính xác. Symfony cung cấp WebTestCase cho functional testing.
<?php
namespace App\Tests\Api;
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
use App\Entity\Product;
use Doctrine\ORM\EntityManagerInterface;
class ProductApiTest extends ApiTestCase
{
private EntityManagerInterface $em;
protected function setUp(): void
{
$this->em = self::getContainer()->get('doctrine')->getManager();
}
public function testGetProducts(): void
{
$response = static::createClient()->request('GET', '/api/products');
$this->assertResponseIsSuccessful();
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
$this->assertJsonContains(['@type' => 'hydra:Collection']);
}
public function testCreateProduct(): void
{
$response = static::createClient()->request('POST', '/api/products', [
'json' => [
'name' => 'New Product',
'description' => 'Product description',
'price' => '99.99'
],
'headers' => [
'Authorization' => 'Bearer ' . $this->getToken()
]
]);
$this->assertResponseStatusCodeSame(201);
$this->assertJsonContains(['name' => 'New Product']);
}
public function testValidationError(): void
{
$response = static::createClient()->request('POST', '/api/products', [
'json' => [
'name' => '',
'price' => -10
]
]);
$this->assertResponseStatusCodeSame(422);
}
}Câu Hỏi Phỏng Vấn API Platform 2026
Dưới đây là các câu hỏi thường gặp trong phỏng vấn liên quan đến API Platform:
1. Sự khác biệt giữa State Provider và Data Provider là gì?
State Provider là cách tiếp cận mới trong API Platform 4 linh hoạt hơn. Data Provider đã deprecated và được thay thế bởi State Provider hỗ trợ async operations và type safety tốt hơn.
2. Làm thế nào để triển khai pagination tùy chỉnh?
Pagination có thể được tùy chỉnh thông qua cấu hình resource hoặc bằng cách tạo custom Paginator triển khai PaginatorInterface.
3. Giải thích sự khác biệt giữa normalization và denormalization context?
Normalization context được sử dụng khi dữ liệu được chuyển đổi từ object sang array/JSON (response). Denormalization context được sử dụng khi dữ liệu được chuyển đổi từ JSON sang object (request).
4. Làm thế nào để xử lý quan hệ trong API Platform?
Quan hệ có thể được expose dưới dạng IRI (tham chiếu) hoặc embedded object sử dụng serialization groups. Đối với thao tác lồng nhau, sử dụng subresource hoặc custom operations.
5. OpenAPI là gì và API Platform sử dụng nó như thế nào?
OpenAPI (trước đây là Swagger) là đặc tả cho tài liệu API. API Platform tự động tạo tài liệu OpenAPI dựa trên metadata của resources.
Sẵn sàng chinh phục phỏng vấn Symfony?
Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.
Kết Luận
API Platform cung cấp giải pháp toàn diện để xây dựng REST API với Symfony. Với các tính năng như thao tác CRUD tự động, lọc, phân trang và tài liệu OpenAPI, developer có thể tập trung vào business logic mà không cần viết boilerplate code. Hiểu biết sâu sắc về State Providers, Processors và serialization groups rất quan trọng để tận dụng tối đa API Platform trong các dự án production.
Bạn có tìm ra lỗi trong Symfony không?
Một đoạn mã thật, một lỗi ẩn, mỗi ngày một lượt. Không cần tài khoản để thử.

Viết bởi
Anthony Fillion-MailletNgười sáng lập SharpSkill
Lập trình viên fullstack hơn 10 năm. Anh điều hành SharpSkill và chịu trách nhiệm về mọi nội dung đăng tại đây.
Cập nhật ngày 25 tháng 8, 2026
Chia sẻ
Bài viết liên quan

Bảo mật REST API Symfony năm 2026: OAuth2, Rate Limiting và Câu hỏi Phỏng vấn
Tìm hiểu cách bảo mật REST API Symfony với OAuth2 token introspection, rate limiting và xác thực JWT. Bài viết đề cập các tính năng bảo mật Symfony 7.3, lỗ hổng phổ biến và câu hỏi phỏng vấn kỹ thuật.

API Platform với Symfony 2026: Kiến trúc Hiện đại và Câu hỏi Phỏng vấn
Hướng dẫn toàn diện về API Platform với Symfony năm 2026, bao gồm kiến trúc SmartPlatform, State Providers, custom filters và các câu hỏi phỏng vấn kỹ thuật cho developer.

API Platform GraphQL Symfony: Schema, Mutation và Câu hỏi Phỏng vấn 2026
Hướng dẫn toàn diện tích hợp API Platform GraphQL với Symfony. Tìm hiểu schema tự động, mutation, resolver tùy chỉnh, bảo mật và câu hỏi phỏng vấn kỹ thuật cho developer 2026.