Laravel 13 Pemula #13: Mengenal Relasi – Menghubungkan Tabel Berita dengan Kategori

Tutorial Laravel 13 Pemula • Proyek Web Berita

#13: Mengenal Relasi – Menghubungkan Tabel Berita dengan Kategori

Halo, Detektif Relasi!

Di tutorial sebelumnya, kita sudah membuat tabel news yang memiliki kolom category_id. Tapi apa gunanya kolom itu? Kolom inilah yang menjadi jembatan penghubung antara berita dan kategori. Di Laravel, kita bisa membuat relasi agar kita bisa dengan mudah mengambil nama kategori dari sebuah berita, atau mengambil semua berita dalam satu kategori. Mari kita pahami dengan cara yang menyenangkan!

Tujuan Kita:
  1. Memahami konsep relasi database (one-to-many) antara kategori dan berita.
  2. Menggunakan relasi yang sudah kita buat di model News dan Category.
  3. Belajar Eager Loading agar pengambilan data lebih efisien.
  4. Menampilkan nama kategori di halaman daftar berita.

Analogi Relasi: Seperti Anak dan Ibunya

Bayangkan Kategori adalah seorang Ibu, dan Berita adalah anak-anaknya.

  • Satu Ibu (kategori) bisa memiliki banyak anak (berita). Contoh: Kategori "Olahraga" bisa memiliki berita "Piala Dunia", "Olimpiade", dll.
  • Setiap anak (berita) hanya memiliki satu Ibu (kategori). Contoh: Berita "Piala Dunia" pasti masuk ke kategori "Olahraga", bukan ke kategori lain.

Ini yang disebut one-to-many (satu ke banyak). Di Laravel, kita menggunakan hasMany di model Ibu, dan belongsTo di model Anak.

Langkah 1: Melihat Relasi yang Sudah Kita Buat

Kita sudah menyiapkan relasi di tutorial #12. Mari kita lihat kembali:

Model News (app/Models/News.php)
public function category()
{
    return $this->belongsTo(Category::class);
}

Artinya: Sebuah berita "termasuk ke" (belongs to) satu kategori.

Model Category (app/Models/Category.php)
public function news()
{
    return $this->hasMany(News::class);
}

Artinya: Sebuah kategori "memiliki banyak" (has many) berita.

🔧 Langkah 2: Menggunakan Relasi di Controller

Kita akan buat controller untuk berita. Tapi sebelum itu, mari kita coba relasi di tinker (terminal interaktif Laravel) agar lebih paham.

Mencoba Relasi dengan Tinker

Buka terminal, pastikan di folder proyek, lalu jalankan:

php artisan tinker

Kemudian coba kode berikut:

// Ambil berita dengan ID 1 (pastikan ada)
$news = App\Models\News::find(1);

// Tampilkan judul berita
$news->title;

// Tampilkan nama kategori dari berita ini (menggunakan relasi)
$news->category->name;

// Ambil kategori dengan ID 1
$category = App\Models\Category::find(1);

// Tampilkan semua berita dalam kategori ini
$category->news;

Jika berhasil, kamu akan melihat nama kategori muncul. Keluar dari tinker dengan exit.

Langkah 3: Membuat Controller Berita Sederhana (Index)

Kita akan buat NewsController dengan method index() untuk menampilkan daftar berita beserta nama kategorinya.

php artisan make:controller NewsController

Jalankan perintah:

php artisan make:controller NewsController

Buka app/Http/Controllers/NewsController.php dan isi:

<?php

namespace App\Http\Controllers;

use App\Models\News;
use Illuminate\Http\Request;

class NewsController extends Controller
{
    public function index()
    {
        // Ambil semua berita, termasuk relasi kategori (Eager Loading)
        $news = News::with('category')->latest()->paginate(10);
        
        return view('news-index', compact('news'));
    }
}

Penjelasan:

  • with('category')Eager Loading. Ini akan mengambil data kategori sekaligus saat mengambil berita, sehingga tidak perlu query terpisah untuk setiap berita. Lebih cepat dan efisien.
  • latest() → mengurutkan dari yang terbaru (berdasarkan created_at).
  • paginate(10) → menampilkan 10 berita per halaman.

Langkah 4: Membuat View untuk Daftar Berita

Buat file resources/views/news-index.blade.php

Isi dengan kode berikut:

<!DOCTYPE html>
<html>
<head>
    <title>Daftar Berita</title>
    <style>
        body { font-family: 'Segoe UI', Arial; margin: 20px; background: #f0f2f5; }
        .container { max-width: 1000px; margin: auto; background: white; padding: 20px; border-radius: 12px; }
        h1 { color: #e67e22; }
        table { width: 100%; border-collapse: collapse; }
        th, td { border: 1px solid #ddd; padding: 10px; text-align: left; }
        th { background: #e67e22; color: white; }
        .btn { background: #007bff; color: white; padding: 8px 16px; text-decoration: none; border-radius: 5px; display: inline-block; margin-bottom: 15px; }
        .badge { background: #28a745; color: white; padding: 2px 8px; border-radius: 20px; font-size: 0.8rem; }
    </style>
</head>
<body>
    <div class="container">
        <h1>Daftar Berita</h1>
        <a href="#" class="btn">+ Tambah Berita (nanti)</a>
        
        @if ($news->count() > 0)
            <table>
                <thead>
                    
                        <th>ID</th>
                        <th>Judul</th>
                        <th>Kategori</th>
                        <th>Slug</th>
                        <th>Dibuat</th>
                    
                </thead>
                <tbody>
                    @foreach ($news as $item)
                    
                        {{ $item->id }}
                        {{ $item->title }}
                        
                            <span class="badge">{{ $item->category->name ?? 'Tanpa Kategori' }}</span>
                        
                        {{ $item->slug }}
                        {{ $item->created_at->diffForHumans() }}
                    
                    @endforeach
                </tbody>
            </table>
            <div style="margin-top: 20px;">
                {{ $news->links() }}
            </div>
        @else
            <p>Belum ada berita. Yuk tambah berita pertama!</p>
        @endif
    </div>
</body>
</html>

Perhatikan baris {{ $item->category->name ?? 'Tanpa Kategori' }}. Ini adalah keajaiban relasi! Kita bisa mengakses nama kategori hanya dengan $item->category->name. Operator ?? adalah default jika kategori tidak ada (null).

Langkah 5: Menambahkan Rute untuk Daftar Berita

Update routes/web.php
use App\Http\Controllers\NewsController;

Route::get('/berita', [NewsController::class, 'index'])->name('news.index');

Sekarang buka browser: http://localhost:8000/berita. Kamu akan melihat daftar berita yang sudah ada (jika ada) dengan nama kategori yang muncul. Hebat!

Memahami Eager Loading vs Lazy Loading

  • Lazy Loading (tanpa with): Jika kita hanya menulis News::all(), lalu di view memanggil $news->category->name, Laravel akan menjalankan query tambahan untuk setiap berita (N+1 problem). Ini lambat jika banyak data.
  • Eager Loading (pakai with('category')): Laravel hanya menjalankan 2 query: satu untuk berita, satu untuk semua kategori yang dibutuhkan. Jauh lebih cepat!
Tips: Biasakan menggunakan with() saat mengambil data yang memiliki relasi, terutama di halaman daftar.

Relasi Sebaliknya: Menampilkan Berita dalam Halaman Kategori

Kita juga bisa membuat halaman khusus untuk melihat berita-berita dalam satu kategori. Contoh: /kategori/olahraga. Ini memanfaatkan relasi dari sisi kategori.

Contoh: Menampilkan Berita per Kategori

Di routes/web.php:

Route::get('/kategori/{slug}', [CategoryController::class, 'show'])->name('kategori.show');

Di CategoryController tambahkan method:

public function show($slug)
{
    $category = Category::where('slug', $slug)->firstOrFail();
    $news = $category->news()->latest()->paginate(10);
    return view('kategori-show', compact('category', 'news'));
}

Di view, kamu bisa menampilkan $category->name dan daftar $news. Ini akan kita buat lengkap nanti di tutorial frontend.

Ringkasan Hari Ini

  • ✅ Relasi one-to-many menghubungkan kategori (induk) dengan berita (anak).
  • ✅ Di model, kita menggunakan hasMany dan belongsTo.
  • ✅ Eager loading (with()) membuat pengambilan data lebih efisien.
  • ✅ Kita bisa mengakses nama kategori dari berita dengan $news->category->name.
  • ✅ Kita sudah membuat halaman daftar berita yang menampilkan nama kategori.

Apa Selanjutnya?

Sekarang kita sudah paham relasi. Selanjutnya kita akan membuat CRUD lengkap untuk berita: form tambah berita dengan pilihan kategori (dropdown), upload gambar, edit, dan hapus. Setelah itu, kita akan membangun halaman depan website yang bisa dibaca oleh pengunjung (frontend). Terus semangat!

Hebat! Kamu baru saja menguasai salah satu konsep terpenting dalam database: relasi. Dengan ini, kamu bisa membuat aplikasi yang kompleks seperti toko online (relasi produk-kategori), blog (post-komentar), dan banyak lagi. Selamat!

Seri Tutorial Laravel 13 Pemula – Proyek Web Berita
✨ Selanjutnya: #14: Membuat Upload Gambar – Menyimpan File Gambar Berita dengan Storage Laravel

Lebih baru Lebih lama

نموذج الاتصال