1. Pengenalan Laravel
Laravel adalah framework PHP modern yang dikembangkan oleh Taylor Otwell dan pertama kali dirilis pada tahun 2011. Laravel dirancang untuk membuat pengembangan web menjadi lebih menyenangkan dan produktif dengan menyediakan tools yang elegan dan sintaks yang expressive.
Laravel mengikuti pola arsitektur Model-View-Controller (MVC) dan menyediakan fitur-fitur lengkap seperti routing, templating engine (Blade), ORM (Eloquent), authentication, queue system, dan masih banyak lagi.
Mengapa Memilih Laravel?
| Keunggulan | Penjelasan |
|---|---|
| Sintaks Elegan | Kode yang expressive dan mudah dibaca â "The PHP Framework for Web Artisans" |
| Ekosistem Lengkap | Breeze/Jetstream (auth), Horizon (queues), Telescope (debug), Forge (deploy) |
| Eloquent ORM | ORM yang powerful dan intuitif untuk berinteraksi dengan database |
| Blade Templating | Template engine yang fleksibel dengan inheritance dan komponen |
| Artisan CLI | Command-line tool untuk generate code, migrate, seed, dan banyak lagi |
| Keamanan Bawaan | CSRF protection, hashing, encryption, SQL injection prevention built-in |
| Komunitas Besar | Forum aktif, Laracasts, dokumentasi lengkap, ribuan package tersedia |
Laravel vs Framework PHP Lainnya
| Aspek | Laravel | Symfony | CodeIgniter |
|---|---|---|---|
| Kurva Belajar | đĄ Sedang | đ´ Curam | đĸ Mudah |
| Fitur | đĸ Sangat Lengkap | đĸ Sangat Lengkap | đĄ Dasar |
| ORM | Eloquent | Doctrine | Tidak ada bawaan |
| Templating | Blade | Twig | Native PHP |
| CLI Tools | Artisan | Console | Sparks |
| Performa | đĄ Baik | đĄ Baik | đĸ Cepat |
| Cocok untuk | Semua skala | Enterprise | Proyek kecil |
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â ARSITEKTUR MVC LARAVEL â â â â ââââââââââââ HTTP Request ââââââââââââââââââââ â â â Browser â âââââââââââââē â Routes â â â ââââââââââââ â (web.php/api.php) â â â â ââââââââââŦââââââââââ â â â â â â â ââââââââââŧââââââââââ â â â â Controller â â â â â (Logika bisnis) â â â â ââââââââââŦââââââââââ â â â â â â â ââââââââââââââââââŧââââââââââââ â â â â â â â â â âââââââââââŧâââââââ ââââââââŧâââââââââ â â â â â Model â â View â â â â â â (Eloquent ORM) â â (Blade) â â â â â âââââââââââŦâââââââ âââââââââââââââââ â â â â â â â â â âââââââââââŧâââââââ â â â â â Database â â â â â â (MySQL/PG/SQLite) â â â â ââââââââââââââââââ â â â â â â â ââââââââââââ HTML Response â â â â Browser â âââââââââââââââââââââââââââââââââââââ â â ââââââââââââ â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
2. Instalasi Laravel
Laravel membutuhkan PHP 8.2+, Composer, dan beberapa ekstensi PHP. Berikut panduan instalasi lengkap.
Prasyarat
# Pastikan PHP 8.2+ dan Composer sudah terinstal php --version # PHP 8.2.x atau lebih baru composer --version # Composer version 2.x # Ekstensi PHP yang dibutuhkan: # Ctype, cURL, DOM, Fileinfo, Filter, Hash, Mbstring, # OpenSSL, PCRE, PDO, Session, Tokenizer, XML
Membuat Proyek Laravel Baru
# Cara 1: Menggunakan Laravel Installer (disarankan) composer global require laravel/installer # Buat proyek baru laravel new my-project # Cara 2: Menggunakan Composer langsung composer create-project laravel/laravel my-project # Masuk ke direktori proyek cd my-project # Jalankan development server php artisan serve # Laravel development server started: http://127.0.0.1:8000 # Buka browser dan akses http://127.0.0.1:8000 # Selamat! Laravel berhasil dijalankan đ
Konfigurasi Database
# File: .env (di root proyek Laravel) # Konfigurasi database DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=my_laravel_db DB_USERNAME=root DB_PASSWORD= # Untuk development, bisa pakai SQLite (tidak perlu setup): # DB_CONNECTION=sqlite # DB_DATABASE=/absolute/path/to/database.sqlite # APP_KEY akan otomatis di-generate saat instalasi APP_KEY=base64:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx APP_DEBUG=true APP_URL=http://localhost:8000
Untuk development cepat, gunakan Laravel Herd (macOS/Windows) yang sudah include PHP, Nginx, dan Dnsmasq. Atau gunakan Sail (Docker) dengan ./vendor/bin/sail up untuk environment yang konsisten tanpa install PHP secara lokal.
3. Struktur Proyek Laravel
Memahami struktur direktori Laravel sangat penting untuk development yang efisien.
my-project/ âââ app/ â Kode utama aplikasi â âââ Http/ â â âââ Controllers/ â Controller (logika request) â â âââ Middleware/ â Middleware (filter request) â â âââ Requests/ â Form Request (validasi) â âââ Models/ â Model Eloquent (database) â âââ Services/ â Service classes (logika bisnis) â âââ Providers/ â Service Providers â âââ config/ â Konfigurasi aplikasi â âââ app.php â Konfigurasi umum â âââ database.php â Konfigurasi database â âââ auth.php â Konfigurasi authentication â âââ database/ â âââ migrations/ â Skema database (versioning) â âââ seeders/ â Data dummy untuk testing â âââ factories/ â Factory untuk generate data â âââ public/ â Document root web server â âââ index.php â Entry point aplikasi â âââ assets/ â CSS, JS, images â âââ resources/ â âââ views/ â Template Blade â âââ css/ â Stylesheet source â âââ js/ â JavaScript source â âââ routes/ â Definisi route â âââ web.php â Route untuk web (session, CSRF) â âââ api.php â Route untuk API (stateless) â âââ storage/ â Log, cache, upload file âââ tests/ â Unit & Feature tests âââ .env â Environment variables âââ artisan â CLI tool Laravel âââ composer.json â Dependencies PHP
4. Routing
Routing adalah mekanisme untuk memetakan URL ke controller atau closure yang akan menangani request. Semua route web didefinisikan di routes/web.php.
Route Dasar
<?php
use App\Http\Controllers\HomeController;
use App\Http\Controllers\PostController;
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;
// Route sederhana â closure
Route::get('/', function () {
return view('welcome');
});
// Route dengan parameter
Route::get('/halo/{nama}', function (string $nama) {
return "Halo, $nama!";
});
// Route ke controller (disarankan untuk proyek nyata)
Route::get('/', [HomeController::class, 'index']);
Route::get('/tentang', [HomeController::class, 'tentang']);
// Resource routes â otomatis buat semua CRUD routes!
Route::resource('posts', PostController::class);
// Ini otomatis membuat:
// GET /posts â index()
// GET /posts/create â create()
// POST /posts â store()
// GET /posts/{post} â show()
// GET /posts/{post}/edit â edit()
// PUT /posts/{post} â update()
// DELETE /posts/{post} â destroy()
// Route grouping dengan prefix
Route::prefix('admin')->group(function () {
Route::get('/', [AdminController::class, 'dashboard']);
Route::get('/users', [AdminController::class, 'users']);
Route::get('/settings', [AdminController::class, 'settings']);
});
// Hasil: /admin, /admin/users, /admin/settings
// Named routes â memudahkan redirect dan URL generation
Route::get('/profile', [UserController::class, 'profile'])
->name('user.profile');
// Menggunakan named route
// redirect()->route('user.profile')
// route('user.profile') â "/profile"
// Route dengan constraint
Route::get('/post/{id}', [PostController::class, 'show'])
->where('id', '[0-9]+'); // hanya angka
Route::get('/post/{slug}', [PostController::class, 'showBySlug'])
->where('slug', '[a-z0-9\-]+'); // slug format
?>
Controller
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
// GET /posts â tampilkan semua post
public function index()
{
$posts = Post::latest()->paginate(10);
return view('posts.index', compact('posts'));
}
// GET /posts/create â tampilkan form buat post
public function create()
{
return view('posts.create');
}
// POST /posts â simpan post baru
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
'status' => 'in:draft,published',
]);
$post = Post::create($validated);
return redirect()->route('posts.show', $post)
->with('success', 'Post berhasil dibuat!');
}
// GET /posts/{post} â tampilkan satu post
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
// GET /posts/{post}/edit â tampilkan form edit
public function edit(Post $post)
{
return view('posts.edit', compact('post'));
}
// PUT /posts/{post} â update post
public function update(Request $request, Post $post)
{
$validated = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
]);
$post->update($validated);
return redirect()->route('posts.show', $post)
->with('success', 'Post berhasil diupdate!');
}
// DELETE /posts/{post} â hapus post
public function destroy(Post $post)
{
$post->delete();
return redirect()->route('posts.index')
->with('success', 'Post berhasil dihapus!');
}
}
?>
5. Blade Templating
Blade adalah template engine Laravel yang powerful. Blade file menggunakan ekstensi .blade.php dan mendukung inheritance, komponen, directive, dan banyak lagi.
Layout dan Inheritance
<!-- File: resources/views/layouts/main.blade.php -->
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title', 'BeebaneLabs')</title>
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
<nav class="navbar">
<a href="/">đ Beranda</a>
<a href="/posts">đ Artikel</a>
<a href="/tentang">âšī¸ Tentang</a>
</nav>
<main>
{{-- Flash messages --}}
@if(session('success'))
<div class="alert alert-success">
â
{{ session('success') }}
</div>
@endif
@yield('content')
</main>
<footer>
<p>© 2026 BeebaneLabs</p>
</footer>
@stack('scripts')
</body>
</html>
Child Template
<!-- File: resources/views/posts/index.blade.php -->
@extends('layouts.main')
@section('title', 'Daftar Artikel')
@section('content')
<div class="container">
<h1>đ Daftar Artikel</h1>
<a href="{{ route('posts.create') }}" class="btn btn-primary">
+ Tulis Artikel Baru
</a>
@forelse($posts as $post)
<article class="post-card">
<h2>
<a href="{{ route('posts.show', $post) }}">
{{ $post->title }}
</a>
</h2>
<span class="badge">{{ $post->status }}</span>
<time>{{ $post->created_at->diffForHumans() }}</time>
<p>{{ Str::limit($post->content, 200) }}</p>
</article>
@empty
<p>Belum ada artikel.</p>
@endforelse
{{ $posts->links() }}
</div>
@endsection
Blade Components
<!-- Component: resources/views/components/alert.blade.php -->
@props(['type' => 'info', 'dismissible' => false])
<div {{ $attributes->merge([
'class' => "alert alert-{$type}"
]) }}>
@if($dismissible)
<button class="close" onclick="this.parentElement.remove()">
×
</button>
@endif
{{ $slot }}
</div>
{{-- Menggunakan component --}}
<x-alert type="success" dismissible>
Data berhasil disimpan! â
</x-alert>
<x-alert type="danger">
Terjadi error! â
</x-alert>
{{-- Blade directives lainnya --}}
@if($posts->count() > 0)
<p>Ada {{ $posts->count() }} artikel</p>
@elseif($posts->count() === 0)
<p>Belum ada artikel</p>
@endif
{{-- Loop dengan $loop variable --}}
@foreach($posts as $post)
<p>{{ $loop->iteration }}. {{ $post->title }}
@if($loop->first) (Artikel Terbaru) @endif
@if($loop->last) (Artikel Terlama) @endif
</p>
@endforeach
{{-- Include partial --}}
@include('partials.sidebar', ['categories' => $categories])
6. Eloquent ORM
Eloquent adalah ORM (Object-Relational Mapping) bawaan Laravel yang memudahkan interaksi dengan database menggunakan syntax yang elegan dan expressive. Setiap tabel database direpresentasikan oleh sebuah Model.
Membuat Model dan Migration
# Buat model beserta migration, factory, dan seeder php artisan make:model Post -mfsc # -m = migration # -f = factory # -s = seeder # -c = controller
Migration
<?php
// database/migrations/xxxx_create_posts_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('title');
$table->string('slug')->unique();
$table->text('content');
$table->enum('status', ['draft', 'published'])->default('draft');
$table->string('thumbnail')->nullable();
$table->timestamps(); // created_at & updated_at
$table->softDeletes(); // deleted_at (soft delete)
});
}
public function down(): void
{
Schema::dropIfExists('posts');
}
};
// Jalankan migration
// php artisan migrate
// php artisan migrate:fresh --seed (reset + seed data)
?>
Model Eloquent
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Support\Str;
class Post extends Model
{
use HasFactory, SoftDeletes;
// Kolom yang bisa diisi mass-assignment
protected $fillable = [
'user_id', 'title', 'slug', 'content', 'status', 'thumbnail'
];
// Kolom yang otomatis di-cast
protected $casts = [
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
// Auto-generate slug saat membuat post
protected static function boot()
{
parent::boot();
static::creating(function ($post) {
$post->slug = Str::slug($post->title) . '-' . Str::random(5);
});
}
// ===== RELATIONSHIPS =====
// Post belongs to a User
public function user()
{
return $this->belongsTo(User::class);
}
// Post has many Comments
public function comments()
{
return $this->hasMany(Comment::class);
}
// Post belongs to many Tags (many-to-many)
public function tags()
{
return $this->belongsToMany(Tag::class);
}
// ===== SCOPES =====
// Scope: hanya post yang published
public function scopePublished($query)
{
return $query->where('status', 'published');
}
// Scope: cari berdasarkan keyword
public function scopeSearch($query, $keyword)
{
return $query->where('title', 'like', "%{$keyword}%")
->orWhere('content', 'like', "%{$keyword}%");
}
// ===== ACCESSORS =====
// Format tanggal Indonesia
public function getFormattedDateAttribute(): string
{
return $this->created_at->translatedFormat('d F Y');
}
}
?>
Query dengan Eloquent
<?php
use App\Models\Post;
// Mengambil semua data
$posts = Post::all();
// Mengambil dengan filter
$published = Post::where('status', 'published')
->orderBy('created_at', 'desc')
->take(10)
->get();
// Menggunakan scope
$posts = Post::published()->search('Laravel')->get();
// Pagination
$posts = Post::published()->paginate(15);
// Mengambil satu data
$post = Post::find(1); // by ID
$post = Post::where('slug', $slug)->first(); // by column
$post = Post::findOrFail(1); // 404 jika tidak ada
// Eager loading (menghindari N+1 problem!)
$posts = Post::with(['user', 'tags', 'comments'])
->published()
->latest()
->paginate(10);
// Membuat data baru
$post = Post::create([
'title' => 'Belajar Laravel',
'content' => 'Laravel adalah framework yang...',
'status' => 'published',
'user_id' => auth()->id(),
]);
// Update data
$post->update(['title' => 'Judul Baru']);
// Delete
$post->delete(); // soft delete (karena pakai SoftDeletes)
$post->forceDelete(); // permanent delete
$post->restore(); // restore soft deleted
// Aggregation
$count = Post::published()->count();
$avg = Post::avg('views');
$max = Post::max('views');
?>
7. Middleware
Middleware adalah mekanisme untuk memfilter request HTTP sebelum mencapai controller. Middleware bisa digunakan untuk autentikasi, logging, CORS, rate limiting, dan banyak lagi.
Membuat dan Menggunakan Middleware
# Buat middleware baru php artisan make:middleware EnsureIsAdmin php artisan make:middleware CheckAge
<?php
// app/Http/Middleware/EnsureIsAdmin.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class EnsureIsAdmin
{
public function handle(Request $request, Closure $next): Response
{
// Cek apakah user adalah admin
if (!auth()->check() || auth()->user()->role !== 'admin') {
abort(403, 'Akses ditolak. Hanya admin yang diizinkan.');
}
return $next($request);
}
}
// app/Http/Middleware/CheckAge.php
class CheckAge
{
public function handle(Request $request, Closure $next, string $minAge): Response
{
if ($request->user()->age < (int) $minAge) {
return redirect('/too-young')
->with('error', "Anda harus berusia minimal $minAge tahun.");
}
return $next($request);
}
}
?>
Mendaftarkan Middleware
<?php
// routes/web.php â menggunakan middleware pada routes
// Single middleware
Route::get('/admin', [AdminController::class, 'dashboard'])
->middleware('auth');
// Multiple middleware
Route::get('/admin/users', [AdminController::class, 'users'])
->middleware(['auth', 'admin']);
// Middleware dengan parameter
Route::get('/premium', [PremiumController::class, 'index'])
->middleware('age:21');
// Group middleware
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
Route::get('/profile', [ProfileController::class, 'edit']);
Route::put('/profile', [ProfileController::class, 'update']);
});
// Admin group
Route::prefix('admin')
->middleware(['auth', 'admin'])
->group(function () {
Route::get('/', [AdminController::class, 'dashboard']);
Route::resource('posts', AdminPostController::class);
Route::resource('users', AdminUserController::class);
});
?>
8. Artisan CLI
Artisan adalah command-line interface bawaan Laravel yang menyediakan puluhan perintah untuk mempercepat development.
Perintah Artisan yang Sering Digunakan
# ===== GENERATE CODE ===== # Buat controller php artisan make:controller PostController --resource # Buat model + migration + factory + seeder php artisan make:model Post -mfsc # Buat middleware php artisan make:middleware EnsureIsAdmin # Buat form request (validasi terpisah) php artisan make:request StorePostRequest # Buat migration php artisan make:migration create_posts_table # Buat seeder php artisan make:seeder PostSeeder # Buat factory php artisan make:factory PostFactory # ===== DATABASE ===== # Jalankan semua migration php artisan migrate # Rollback migration terakhir php artisan migrate:rollback # Reset dan jalankan ulang semua migration php artisan migrate:fresh # Reset, migrate, dan seed php artisan migrate:fresh --seed # Jalankan seeder php artisan db:seed # ===== ROUTE ===== # Lihat semua route php artisan route:list # Lihat route tertentu php artisan route:list --name=post # ===== CACHE & OPTIMIZATION ===== # Clear semua cache php artisan cache:clear php artisan config:clear php artisan route:clear php artisan view:clear # Cache untuk production php artisan config:cache php artisan route:cache php artisan view:cache # ===== LAINNYA ===== # Jalankan development server php artisan serve --port=8080 # Buat symbolic link storage php artisan storage:link # List semua artisan commands php artisan list # Bantuan untuk command tertentu php artisan help migrate
Custom Artisan Command
<?php
// php artisan make:command SendDailyReport
namespace App\Console\Commands;
use Illuminate\Console\Command;
class SendDailyReport extends Command
{
protected $signature = 'report:daily {--email= : Email tujuan}';
protected $description = 'Kirim laporan harian ke email admin';
public function handle(): int
{
$email = $this->option('email') ?? 'admin@beebanelabs.com';
$this->info("Mengirim laporan harian ke $email...");
$this->line(""); // empty line
$this->warn("Pastikan koneksi internet aktif!");
// Progress bar
$bar = $this->output->createProgressBar(100);
$bar->start();
for ($i = 0; $i < 100; $i++) {
// Proses data...
usleep(50000); // simulasi proses
$bar->advance();
}
$bar->finish();
$this->newLine(2);
$this->info("â
Laporan berhasil dikirim ke $email!");
return Command::SUCCESS; // exit code 0
}
}
// Jalankan: php artisan report:daily --email=admin@example.com
?>
9. Form Validation
Laravel menyediakan sistem validasi yang sangat powerful dan mudah digunakan.
<?php
// Validasi langsung di controller
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|string|max:255|unique:posts,title',
'content' => 'required|string|min:50',
'email' => 'required|email|unique:users',
'password' => 'required|string|min:8|confirmed',
'age' => 'required|integer|min:17|max:100',
'avatar' => 'nullable|image|mimes:jpg,png|max:2048',
'website' => 'nullable|url',
'tags' => 'array|min:1',
'tags.*' => 'string|exists:tags,id',
], [
// Custom error messages (Bahasa Indonesia)
'title.required' => 'Judul wajib diisi!',
'title.max' => 'Judul maksimal 255 karakter.',
'content.min' => 'Konten minimal 50 karakter.',
'email.email' => 'Format email tidak valid.',
'age.min' => 'Usia minimal 17 tahun.',
]);
Post::create($validated);
}
// Form Request â validasi terpisah (lebih rapi)
// php artisan make:request StorePostRequest
// app/Http/Requests/StorePostRequest.php
class StorePostRequest extends FormRequest
{
public function authorize(): bool
{
return auth()->check();
}
public function rules(): array
{
return [
'title' => 'required|string|max:255',
'content' => 'required|string|min:50',
'status' => 'in:draft,published',
];
}
public function messages(): array
{
return [
'title.required' => 'Judul tidak boleh kosong!',
'content.min' => 'Tulisan minimal 50 karakter.',
];
}
}
// Menggunakan Form Request di controller
public function store(StorePostRequest $request)
{
// Data sudah tervalidasi di StorePostRequest
$post = Post::create($request->validated());
return redirect()->route('posts.show', $post)
->with('success', 'Artikel berhasil dipublikasikan!');
}
?>
10. Quiz: Uji Pemahamanmu!
Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang Laravel: