API Subresources di API Platform
API Platform mendukung fitur subresources, yaitu endpoint turunan dari entitas lain, misalnya: GET /api/users/1/comments
Fitur ini sangat berguna untuk menggambarkan relasi antar entitas (misal: satu User memiliki banyak Comment) secara RESTful dan otomatis.
1. Apa Itu Subresource?
Subresource adalah endpoint otomatis yang tersedia dari relasi antar entitas yang diberi anotasi #[ApiSubresource].
Contoh:
GET /api/authors/1/booksGET /api/categories/2/products
2. Contoh Kasus: User & Comment
Entitas User
use ApiPlatform\Metadata\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use ApiPlatform\Metadata\ApiSubresource;
#[ApiResource]
class User
{
#[ORM\OneToMany(mappedBy: 'user', targetEntity: Comment::class)]
#[ApiSubresource]
private Collection $comments;
public function __construct()
{
$this->comments = new ArrayCollection();
}
public function getComments(): Collection
{
return $this->comments;
}
}
Entitas Comment
#[ApiResource]
class Comment
{
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'comments')]
#[ORM\JoinColumn(nullable: false)]
private ?User $user = null;
}
3. Hasil Endpoint
Dengan konfigurasi di atas, secara otomatis akan tersedia endpoint:
GET /api/users/{id}/comments
Yang akan mengembalikan semua komentar milik user dengan ID tertentu.
4. Pengaturan Pagination, Normalization
Kamu bisa menambahkan pengaturan khusus pada relasi subresource, misalnya:
#[ApiSubresource(maxDepth: 1)]
Atau menambahkan pengaturan context pada operasi GET:
#[ApiResource(
normalizationContext: ['groups' => ['comment:read']],
denormalizationContext: ['groups' => ['comment:write']]
)]
5. Filtering Subresource
Subresource juga bisa digunakan bersama filter. Misalnya:
GET /api/users/1/comments?order[createdAt]=desc
Pastikan filter diaktifkan di entitas target (Comment)`.
6. Membatasi Akses Subresource
Kamu bisa menggunakan security expression di ApiResource atau di operasi GET untuk membatasi siapa yang bisa mengakses:
#[ApiResource(
operations: [
new GetCollection(security: "is_granted('ROLE_ADMIN')")
]
)]
Atau di level global:
#[ApiSubresource]
#[Groups(['user:read'])]
7. Subresource Bukan Replace GET Utama
Endpoint /api/comments?user=/api/users/1 tetap tersedia, subresource hanya tambahan, bukan pengganti. Tapi lebih RESTful dan eksplisit.
8. Penting Diperhatikan
-
Gunakan
#[ApiSubresource]di sisi relasi "parent" (OneToMany,ManyToMany) -
Gunakan serialization group yang tepat agar data tersaji sesuai kebutuhan
-
Untuk menonaktifkan subresource default, hapus anotasi
#[ApiSubresource]
- Contoh Response Request:
GET /api/users/1/comments
Response:
[
{
"@id": "/api/comments/10",
"content": "Komentar A"
},
{
"@id": "/api/comments/12",
"content": "Komentar B"
}
]
Kesimpulan
✅ Subresources mempermudah akses relasi antar entitas
✅ Menyediakan struktur URL RESTful dan intuitif
✅ Bisa digabung dengan filter, pagination, security
✅ Gunakan #[ApiSubresource] untuk mengaktifkan
🧩 Cocok untuk menyederhanakan frontend fetching seperti: user.comments, author.books, category.products, dll.