Selamat datang kembali di seri tutorial Laravel. Setelah mempelajari relasi One To One dan One To Many, kini kita akan membahas jenis relasi yang lebih kompleks namun sangat berguna: Many To Many (Banyak ke Banyak).
Relasi Many To Many menggambarkan hubungan di mana banyak instance dari satu model dapat berelasi dengan banyak instance dari model lain, dan sebaliknya. Contoh umum meliputi:
- Satu Student dapat mengambil banyak Courses, dan satu Course dapat diambil oleh banyak Students.
- Satu Post dapat memiliki banyak Tags, dan satu Tag dapat dimiliki oleh banyak Posts.
- Satu Order dapat memiliki banyak Products, dan satu Product dapat termasuk dalam banyak Orders.
Untuk mengelola relasi Many To Many di database, kita biasanya memerlukan tabel perantara (pivot table). Pada tutorial ini, kita akan menggunakan contoh relasi antara Post dan Tag.
Persiapan Awal
Pastikan Anda sudah memiliki hal-hal berikut:
- Proyek Laravel: Proyek Laravel Anda sudah berjalan dan terhubung ke database.
- Migration untuk Tabel: Kita akan membuat tiga tabel:
posts,tags, dan tabel pivotpost_tag.Migration untuk Tabel
posts:“`bash
php artisan make:migration create_posts_table –create=posts
“`
Modifikasi file migration
create_posts_table:“`php
public function up()
{
Schema::create(‘posts’, function (Blueprint $table) {
$table->id();
$table->string(‘title’);
$table->text(‘body’);
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists(‘posts’);
}
“`
Migration untuk Tabel
tags:“`bash
php artisan make:migration create_tags_table –create=tags
“`
Modifikasi file migration
create_tags_table:“`php
public function up()
{
Schema::create(‘tags’, function (Blueprint $table) {
$table->id();
$table->string(‘name’)->unique();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists(‘tags’);
}
“`
Migration untuk Tabel Pivot
post_tag:Nama tabel pivot biasanya merupakan gabungan dari nama kedua tabel yang berelasi dalam urutan alfabet (misalnya,
postdantagmenjadipost_tag).“`bash
php artisan make:migration create_post_tag_table –create=post_tag
“`
Modifikasi file migration
create_post_tag_table:“`php
public function up()
{
Schema::create(‘post_tag’, function (Blueprint $table) {
$table->id();
$table->foreignId(‘post_id’)->constrained()->onDelete(‘cascade’);
$table->foreignId(‘tag_id’)->constrained()->onDelete(‘cascade’);
$table->timestamps();
$table->unique(['post_id', 'tag_id']); // Mencegah duplikasi relasi });}
public function down()
{
Schema::dropIfExists(‘post_tag’);
}
“`
- Perhatikan bahwa tabel pivot memiliki dua kolom foreign key,
post_idyang merujuk ke tabelposts, dantag_idyang merujuk ke tabeltags. - Kita juga mendefinisikan indeks unik pada kombinasi
post_iddantag_iduntuk memastikan bahwa setiap kombinasi postingan dan tag hanya dapat muncul satu kali. onDelete('cascade')memastikan jika sebuah postingan atau tag dihapus, relasi di tabel pivot juga akan terhapus.
Jalankan migration Anda:
“`bash
php artisan migrate
“`
- Perhatikan bahwa tabel pivot memiliki dua kolom foreign key,
- Model: Buat dua model yang sesuai:
PostdanTag.“`bash
php artisan make:model Post
php artisan make:model Tag
“`
Langkah 2: Mendefinisikan Relasi di Model Eloquent
Sekarang, kita definisikan relasi Many To Many di kedua model.
Model Post.php (app/Models/Post.php)
Tambahkan method tags() yang mendefinisikan relasi dengan model Tag.
“`php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Post extends Model
{
use HasFactory;
protected $fillable = ['title', 'body'];
/**
* The tags that belong to the post.
*/
public function tags(): BelongsToMany
{
return $this->belongsToMany(Tag::class);
}
}
“`
belongsToMany(Tag::class): Metode ini menunjukkan relasi Many To Many dengan modelTag. Eloquent secara otomatis akan mencari tabel pivot bernamapost_tagdan menggunakan kolompost_iddantag_idsebagai foreign key.
Model Tag.php (app/Models/Tag.php)
Tambahkan method posts() yang mendefinisikan relasi kebalikannya dengan model Post.
“`php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Tag extends Model
{
use HasFactory;
protected $fillable = ['name'];
/**
* The posts that belong to the tag.
*/
public function posts(): BelongsToMany
{
return $this->belongsToMany(Post::class);
}
}
“`
- Sama seperti di model
Post,belongsToMany(Post::class)mendefinisikan relasi Many To Many dengan modelPost, menggunakan tabel pivotpost_tagdan kolom-kolom yang sesuai.
Langkah 3: Berinteraksi dengan Relasi Many To Many
Sekarang kita bisa berinteraksi dengan relasi ini di controller atau di artisan tinker.
Melampirkan (Attaching) Tag ke Postingan
Untuk menghubungkan satu atau beberapa tag ke sebuah postingan, gunakan metode attach().
“`php
use App\Models\Post;
use App\Models\Tag;
$post = Post::find(1);
$tag1 = Tag::find(1);
$tag2 = Tag::find(2);
$post->tags()->attach($tag1); // Melampirkan satu tag
$post->tags()->attach([$tag2->id, 3]); // Melampirkan beberapa tag (ID bisa langsung diberikan)
“`
Melepas (Detaching) Tag dari Postingan
Untuk memutuskan hubungan antara satu atau beberapa tag dari sebuah postingan, gunakan metode detach().
“`php
$post = Post::find(1);
$post->tags()->detach($tag1); // Melepas satu tag
$post->tags()->detach([$tag2->id, 3]); // Melepas beberapa tag
$post->tags()->detach(); // Melepas semua tag dari postingan
“`
Menyinkronkan (Syncing) Tag dengan Postingan
Metode sync() menerima array ID untuk ditempatkan pada tabel pivot. ID apa pun yang tidak ada dalam array akan dilepas. Ini seperti “mengganti” semua tag yang terkait dengan postingan.
“`php
$post = Post::find(1);
$post->tags()->sync([1, 3, 5]); // Hanya tag dengan ID 1, 3, dan 5 yang akan terkait
“`
Anda juga dapat menyertakan kolom pivot tambahan dengan sync():
“`php
$post->tags()->sync([
1 => [‘created_at’ => now(), ‘updated_at’ => now()],
3,
]);
“`
Mengambil Data dengan Relasi (Eager Loading)
Untuk menghindari masalah N+1 query, gunakan eager loading dengan metode with().
“`php
use App\Models\Post;
$posts = Post::with(‘tags’)->get();
foreach ($posts as $post) {
echo “Judul Postingan: ” . $post->title . “<br>”;
echo “Tag: “;
foreach ($post->tags as $tag) {
echo “- ” . $tag->name . ” “;
}
echo “<br><hr>”;
}
use App\Models\Tag;
$tags = Tag::with(‘posts’)->get();
foreach ($tags as $tag) {
echo “Nama Tag: ” . $tag->name . “<br>”;
echo “Postingan Terkait: “;
foreach ($tag->posts as $post) {
echo “- ” . $post->title . ” “;
}
echo “<br><hr>”;
}
“`
Mengakses Kolom Pivot
Secara default, instance model yang dikembalikan melalui relasi Many To Many hanya berisi atribut dari tabel terkait. Namun, tabel pivot juga memiliki kolom (id, post_id, tag_id, created_at, updated_at, dan kolom pivot tambahan lainnya jika ada). Anda dapat mengakses atribut ini menggunakan properti pivot pada model yang terkait:
“`php
$post = Post::with(‘tags’)->find(1);
foreach ($post->tags as $tag) {
echo “Tag: ” . $tag->name . “<br>”;
echo “Waktu Dilampirkan: ” . $tag->pivot->created_at . “<br>”;
echo “<hr>”;
}
“`
Kesimpulan
Relasi Many To Many di Laravel Eloquent memberikan cara yang elegan dan mudah untuk mengelola hubungan yang kompleks antar model melalui tabel perantara. Dengan metode seperti attach(), detach(), dan sync(), serta fitur eager loading, Anda dapat dengan efisien memanipulasi dan mengambil data dalam relasi banyak ke banyak. Pemahaman relasi ini sangat penting untuk membangun aplikasi web dengan struktur data yang kaya dan saling terhubung.
Pada tutorial selanjutnya, kita akan menjelajahi jenis-jenis relasi Eloquent lainnya dan fitur-fitur canggih yang ditawarkan. Tetap ikuti seri tutorial Laravel ini dari Malang, Jawa Timur!