Relasi Antar Entity di API Platform
Dalam API Platform, relasi antar entitas (OneToMany, ManyToOne, ManyToMany, OneToOne) secara otomatis dikonversi menjadi relasi API, termasuk pengelolaan data dan serialisasi JSON.
Contoh Kasus: Book & Author
Misalnya kita memiliki 2 entitas: Author
dan Book
. Setiap Book
ditulis oleh satu Author
(ManyToOne), dan satu Author
bisa menulis banyak Book
(OneToMany).
1. Entity Author
<?php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[ApiResource]
class Author
{
#[ORM\Id, ORM\GeneratedValue, ORM\Column]
private ?int $id = null;
#[ORM\Column]
private string $name;
#[ORM\OneToMany(mappedBy: 'author', targetEntity: Book::class)]
private Collection $books;
public function __construct()
{
$this->books = new ArrayCollection();
}
// Getter dan Setter
}
2. Entity Book
<?php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[ApiResource]
class Book
{
#[ORM\Id, ORM\GeneratedValue, ORM\Column]
private ?int $id = null;
#[ORM\Column]
private string $title;
#[ORM\ManyToOne(targetEntity: Author::class, inversedBy: 'books')]
#[ORM\JoinColumn(nullable: false)]
private ?Author $author = null;
// Getter dan Setter
}
Struktur JSON (Default)
Endpoint GET /api/books/1
akan mengembalikan:
{
"@id": "/api/books/1",
"@type": "Book",
"id": 1,
"title": "Judul Buku",
"author": "/api/authors/2"
}
Endpoint GET /api/authors/2
akan mengembalikan:
{
"@id": "/api/authors/2",
"@type": "Author",
"id": 2,
"name": "Penulis",
"books": ["/api/books/1", "/api/books/3"]
}
Serialization Groups (Menampilkan Data Relasi) Secara default, relasi hanya menampilkan IRI (URL). Jika ingin menampilkan detail objek, Anda bisa menggunakan Serialization Groups.
Tambahkan Group
use Symfony\Component\Serializer\Annotation\Groups;
#[ApiResource(normalizationContext: ['groups' => ['book:read']])]
class Book
{
#[Groups(['book:read'])]
#[ORM\Column]
private string $title;
#[Groups(['book:read'])]
#[ORM\ManyToOne(targetEntity: Author::class)]
private ?Author $author = null;
}
Dan di Author
:
#[Groups(['book:read'])]
#[ORM\Column]
private string $name;
Dengan konfigurasi ini, endpoint GET /api/books/1
akan mengembalikan:
{
"id": 1,
"title": "Judul Buku",
"author": {
"id": 2,
"name": "Penulis"
}
}
Cascade Persist (Opsional)
Jika ingin saat menyimpan Book
sekaligus menyimpan Author:
#[ORM\ManyToOne(targetEntity: Author::class, cascade: ['persist'])]
private ?Author $author = null;
Filtering Berdasarkan Relasi Aktifkan filter berdasarkan relasi:
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Metadata\ApiFilter;
#[ApiFilter(SearchFilter::class, properties: ['author' => 'exact'])]
class Book { ... }
Gunakan query:
GET /api/books?author=/api/authors/2