Kali ini kita akan bahas mekanisme register dari Breeze, Coba perhatikan folder routes
pada project, Disana akan ada file baru bernama auth.php
dan file ini memang di buat otomatis oleh Breeze untuk mengatur fitur-fitur route yang di butuhkan oleh Breeze itu sendiri. Sekarang mari buka file web.php
, Kurang lebih isinya akan seperti ini :
<?php
use App\Http\Controllers\ChirpController;
use App\Http\Controllers\ProfileController;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
Route::middleware('auth')->group(function () {
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});
Route::resource('chirps', ChirpController::class)
->only(['index', 'store', 'edit', 'update', 'destroy'])
->middleware(['auth', 'verified']);
require __DIR__.'/auth.php';
Perhatikan pada kode di nomor 7 – 9, Kode tersebut mendefinisikan rute untuk URL root /
dari aplikasi dan rute tersebut menggunakan metode get
, yang berarti akan merespons permintaan HTTP GET ke URL root.
Di rute tersebut terdapat sebuah fungsi anonim yang memanggil fungsi view
untuk mengembalikan tampilan (view) yang bernama welcome.blade.php
. Jadi secara default, Saat aplikasi di akses maka kode itu yang akan di jalankan dan menampilkan halaman welcome
yang terdapat pada folder resources\views
. Kurang lebih tampilannya seperti ini

Sekarang buka file welcome.blade.php
dan cari kode ini di file tersebut
<header class="grid grid-cols-2 items-center gap-2 py-10 lg:grid-cols-3">
<div class="flex lg:justify-center lg:col-start-2">
<svg class="h-12 w-auto text-white lg:h-16 lg:text-[#FF2D20]" viewBox="0 0 62 65" fill="none" xmlns="" fill="currentColor"/></svg>
</div>
@if (Route::has('login'))
<nav class="-mx-3 flex flex-1 justify-end">
@auth
<a
href="{{ url('/dashboard') }}"
class="rounded-md px-3 py-2 text-black ring-1 ring-transparent transition hover:text-black/70 focus:outline-none focus-visible:ring-[#FF2D20] dark:text-white dark:hover:text-white/80 dark:focus-visible:ring-white"
>
Dashboard
</a>
@else
<a
href="{{ route('login') }}"
class="rounded-md px-3 py-2 text-black ring-1 ring-transparent transition hover:text-black/70 focus:outline-none focus-visible:ring-[#FF2D20] dark:text-white dark:hover:text-white/80 dark:focus-visible:ring-white"
>
Log in
</a>
@if (Route::has('register'))
<a
href="{{ route('register') }}"
class="rounded-md px-3 py-2 text-black ring-1 ring-transparent transition hover:text-black/70 focus:outline-none focus-visible:ring-[#FF2D20] dark:text-white dark:hover:text-white/80 dark:focus-visible:ring-white"
>
Register
</a>
@endif
@endauth
</nav>
@endif
</header>
Kode nomor 5 sampai 32 adalah kode yang bertugas untuk menampilkan link Login
dan Register
pada halaman welcome
. Kira kira begini logika keseluruhan kode tersebut
1. @if (Route::has('login'))
: code ini akan memeriksa apakah rute login
ada. Jika ada maka blok kode di dalamnya akan di eksekusi dan jika tidak ada maka link login
dan Register
tidak akan muncul di halaman welcome
.
2. @auth : Direktif ini akan memeriksa apakah pengguna saat ini sudah login. Jika sudah maka aplikasi akan menampilkan link Dashboard
.
3. @if (Route::has('register'))
: Kode ini akan melakukan pemeriksaan apakah rute register tersedia. Jika tidak maka link Register
tidak akan di tampilkan.
Jadi ketika pengguna mengklik link register maka aplikasi laravel akan menangani proses tersebut di file web.php
, Karena rute itu di buat dari Breeze secara otomatis di file terpisah yaitu auth.php
maka di file web.php
perlu meload file auth.php
dengan menggunakan kode require __DIR__.'/auth.php';
.
Perlu diketahui bahwa jika rute <a href="{{ route('register') }}">
tidak dideskripsikan secara eksplisit, maka secara default, rute ini akan mengarah ke metode GET. Ini adalah perilaku bawaan dari Laravel ketika menggunakan fungsi route()
di dalam tautan (link). Jadi sekarang mari kita buka file auth.php
dan mencari kode rute untuk register yang menggunakan metode GET.
<?php
use App\Http\Controllers\Auth\AuthenticatedSessionController;
use App\Http\Controllers\Auth\ConfirmablePasswordController;
use App\Http\Controllers\Auth\EmailVerificationNotificationController;
use App\Http\Controllers\Auth\EmailVerificationPromptController;
use App\Http\Controllers\Auth\NewPasswordController;
use App\Http\Controllers\Auth\PasswordController;
use App\Http\Controllers\Auth\PasswordResetLinkController;
use App\Http\Controllers\Auth\RegisteredUserController;
use App\Http\Controllers\Auth\VerifyEmailController;
use Illuminate\Support\Facades\Route;
Route::middleware('guest')->group(function () {
Route::get('register', [RegisteredUserController::class, 'create'])
->name('register');
Route::post('register', [RegisteredUserController::class, 'store']);
Route::get('login', [AuthenticatedSessionController::class, 'create'])
->name('login');
Route::post('login', [AuthenticatedSessionController::class, 'store']);
Route::get('forgot-password', [PasswordResetLinkController::class, 'create'])
->name('password.request');
Route::post('forgot-password', [PasswordResetLinkController::class, 'store'])
->name('password.email');
Route::get('reset-password/{token}', [NewPasswordController::class, 'create'])
->name('password.reset');
Route::post('reset-password', [NewPasswordController::class, 'store'])
->name('password.store');
});
Route::middleware('auth')->group(function () {
Route::get('verify-email', EmailVerificationPromptController::class)
->name('verification.notice');
Route::get('verify-email/{id}/{hash}', VerifyEmailController::class)
->middleware(['signed', 'throttle:6,1'])
->name('verification.verify');
Route::post('email/verification-notification', [EmailVerificationNotificationController::class, 'store'])
->middleware('throttle:6,1')
->name('verification.send');
Route::get('confirm-password', [ConfirmablePasswordController::class, 'show'])
->name('password.confirm');
Route::post('confirm-password', [ConfirmablePasswordController::class, 'store']);
Route::put('password', [PasswordController::class, 'update'])->name('password.update');
Route::post('logout', [AuthenticatedSessionController::class, 'destroy'])
->name('logout');
});
Dari kode di atas, rute untuk menangani register dengan metode GET berada di baris 15 – 16 dan dari kode tersebut tampaknya kita di arahkan ke file RegisteredUserController
yang berada di folder `
Dari kode di atas, rute untuk menangani register dengan metode GET berada di baris 15 – 16 dan dari kode tersebut tampaknya kita di arahkan ke file RegisteredUserController
yang berada di folder App\Http\Controllers\Auth
dan spesifik pada fungsi yang bernama create
yang berada pada file tersebut. Jadi mari kita buka kode dari file tersebut.
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules;
use Illuminate\View\View;
class RegisteredUserController extends Controller
{
/**
* Display the registration view.
*/
public function create(): View
{
return view('auth.register');
}
/**
* Handle an incoming registration request.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request): RedirectResponse
{
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
event(new Registered($user));
Auth::login($user);
return redirect(route('dashboard', absolute: false));
}
}
Mari kita pahami bagaimana kode itu bekerja,
Pertama adalah fungsi create
di buat dengan deklarasi tipe pengembalian : View
yang menjelaskan bahwa fungsi ini mengharapkan pengembalian dengan tipe View
, Sementara kode return view('auth.register');
menjelaskan bahwa dia akan mengembalikan view yang berada di folder resources\views\auth\register.blade.php
.
Jadi secara singkatnya ketika pengguna mengklik link Register
maka laravel akan membuka file register.blade.php
untuk menampilkan semua user interface ke pengguna.
Kedua adalah fungsi store yang di buat dengan tipe pengembalian RedirectResponse
yang menjelaskan bahwa fungsi ini harus mengembalikan sebuah redirect route, Kemudian pada bagian $request->validate
itu berfungsi untuk memvalidasi request jadi semisal fungsi ini di jalankan dan properti email tidak di sertakan maka fungsi ini akan memberi informasi bahwa email di perlukan untuk menjalankan fungsi ini. Lalu User::create
berfungsi untuk membuat data yang telah di validasi dan data ini dibuat menggunakan Eloquent
. Setelah itu ada kode event(new Registered($user));
kode ini bengfungsi untuk memicu event
Registered yang dalam kasus ini dia akan mengirimkan email verifikasi ke pengguna.
Seperti yang saya katakan pada part 1 dari tutorial ini, bahwa Breeze juga membuat fitur verifikasi email yang bertujuan untuk memberi proteksi lebih terhadap aplikasi dengan cara mencegah user mengakses halaman tertentu yang menggunakan middleware verified
, namun fitur itu tidak langsung berfungsi sebelum kita mengimplementasikan contract
Illuminate\Contracts\Auth\MustVerifyEmail
pada model App\Models\User
.
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable;
}
Ketika contract
sudah di gunakan dan server mail sudah di atur, saat ada pengguna mendaftar akan secara otomatis di kirimi sebuah email yang berisi verifikasi link. Itu terjadi karena laravel sudah mendaftarkan listener
Illuminate\Auth\Listeners\SendEmailVerificationNotification
untuk event
Illuminate\Auth\Events\Registered
.
Jadi ketika kode event(new Registered($user));
di jalakan secara otomatis laravel akan mengirim email verifikasi ke properti email yang ada di dalam $user
.
Sekarang kita kembali lagi ke fungsi store tadi, setelah kode untuk event di picu kode berikutnya adalah Auth::login($user);
yang berfungsi untuk otomatis login setelah mendaftar kemudian kode return redirect(route('dashboard', absolute : false));
yang mengarahkan kita ke rute yang bernama dashboard
, btw setelah kamu secara otomatis login ke aplikasi mungkin kamu berfikir sudah bisa mengakses halaman dashboard, Tapi dugaan kamu itu salah karena kamu akan di arahkan ke halaman verifikasi email, rute apa pun yang kamu akses saat kamu sudah login pasti kamu akan tetap di arahkan ke halaman verifikasi email.
Hal itu terjadi karena model User
sudah mengimplementasikan interface MustVerifyEmail
dan rute yang kamu akses tidak hanya dilindungi oleh middleware auth
namun juga verified
, kedua middleware itu memang sudah bawaan laravel. Jadi meskipun kamu sudah login namun tidak melakukan verifikasi email maka middleware verified
akan mengarahkan kamu ke rute yang bernama verification.notice
dan nama rute itu sudah paten karna sudah di tetapkan di middleware bawaan laravel jadi jangan rubah nama rute tersebut.
## ROUTE
Route::middleware('auth')->group(function () {
Route::get('verify-email', EmailVerificationPromptController::class)
->name('verification.notice');
});
## CONTROLLER
class EmailVerificationPromptController extends Controller
{
/**
* Display the email verification prompt.
*/
public function __invoke(Request $request): RedirectResponse|View
{
return $request->user()->hasVerifiedEmail()
? redirect()->intended(route('dashboard', absolute: false))
: view('auth.verify-email');
}
}
Coba sekarang kamu pahami sejenak potongan kode tersebut, kode itulah yang memaksa pengguna harus melakukan verifikasi sebelum menggunakan aplikasi. Jika kesulitan memahami cara kerja kode tersebut silahkan baca penjelasan ku :p.
Ingat bahwa rute untuk dashboard menggunakan middleware bawaan laravel yaitu verified
, middleware itu akan selalu memeriksa apakah akun pengguna sudah terverifikasi?, Jika belum maka akan di arahkan ke rute yang bernama verification.notice
dan kode tersebut ada di kode nomor 4 dan rute itu menggunakan EmailVerificationPromptController
untuk menangani permintaan yang datang ke rute tersebut.
Alih-alih kontroller tersebut menggunakan nama fungsi sebagai pada umumnya, justru hanya ada satu fungsi dan itu adalah __invoke
dan itu juga salah satu fitur dari laravel yaitu Single Action Controller
yang intinya adalah ketika rute verification.notice
di akses maka laravel akan otomatis menjalankan metode __invoke
yang berada di kontroller EmailVerificationPromptController
. Jika ingin tau lebih soal ini bisa baca di sini.
Nah sekarang kita bahas isi dari metode itu, pertama $request
Variabel ini mewakili objek Illuminate\Http\Request
yang mewakili permintaan HTTP yang masuk ke aplikasi Laravel, lalu objek user di ambil dari $request dengan cara $request->user()
untuk di lakukan pengecekan apakah user tersebut telah melakukan verifikasi email dengan cara menambahkan hasVerifiedEmail()
dan metode ini mengembalikan nilai TRUE
atau FALSE
. Jadi kode $request->user()->hasVerifiedEmail()
adalah memeriksa mengambil objek user dari data request yang datang menggunakan metode hashVerifiedEmail.
Kemudian menggunakan ternary
jika belum terverifikasi maka akan menjalankan kode view('auth.verify-email');
yang akan membuka halaman verifikasi email sementara jika sudah maka akan menjalankan kode redirect()->intended(route('dashboard', absolute: false))
.redirect()
adalah fungsi global laravel yang mengembalikan instance dari RedirectResponse
dan fungsi ini digunakan untuk mengarahkan pengguna ke URL berbeda. intended()
adalah salah satu metode dari RedirectResponse
yang akan mengarahkan pengguna ke URL yang sebelumnya di akses tapi belum login, jadi semisal kamu belum login dan memaksa mengakses halaman transaksi kamu akan terhalang middleware namun setelah login kamu akan di arahkan ke halaman transaksi namun jika kamu tidak mengakses halaman apapun sebelum login maka kamu akan di arahkan ke rute dashboard dengan menggunakan parameter absolute: false
untuk memastikan bahwa URL yang dihasilkan adalah URL relatif, bukan absolut.
redirect()->intended(route(‘dashboard’, absolute:
false));
// Menghasilkan redirect ke URL relatif: /dashboard
redirect()->intended(route(‘dashboard’));
// Menghasilkan redirect ke URL absolut: http://example.com/dashboard
Dalam kebanyakan kasus, menggunakan URL absolut lebih aman karena memastikan bahwa pengalihan akan bekerja dengan benar, terlepas dari konteks tempat pengalihan terjadi. Namun, dalam beberapa situasi khusus (misalnya, jika aplikasi Anda berjalan di beberapa subdomain atau direktori), Anda mungkin memerlukan URL relatif. Untuk lebih lanjut soal redirect dan intended bisa baca di sini.
Aku rasa kamu sudah paham bagaimana Laravel melindungi halaman dari pengguna yang belum memverifikasi email. Sekarang, kamu harus mengerti bagaimana cara Laravel melakukan verifikasi pengguna.
Kode di bawah ini adalah kode untuk menghandle proses verifikasi. Coba kamu pahami kode tersebut. Jika kamu merasa stuck, kamu bisa membaca informasi tambahan di sini. Bila masih stuck, simak penjelasan dariku nanti ;P
## Route
Route::middleware('auth')->group(function () {
Route::get('verify-email/{id}/{hash}', VerifyEmailController::class)
->middleware(['signed', 'throttle:6,1'])
->name('verification.verify');
});
## CONTROLLER
class VerifyEmailController extends Controller
{
/**
* Mark the authenticated user's email address as verified.
*/
public function __invoke(EmailVerificationRequest $request): RedirectResponse
{
if ($request->user()->hasVerifiedEmail()) {
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
}
if ($request->user()->markEmailAsVerified()) {
event(new Verified($request->user()));
}
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
}
}
aku harap kamu benar – benar membaca dokumentasi yang tadi aku berikan, Karna jika iya mungkin kamu kebingungan mengapa kode dari Breeze bisa berbeda dari dokumentasi yang di berikan :D. Sebelum aku mencari tau kenapa hal itu bisa terjadi aku juga sempat bingung kenapa kode dan dokumentasi itu berbeda. Namun setelah aku pahami kembali sebenarnya kode dan dokumentasi itu sama hanya saja caranya yang berbeda, Breeze menggunakan Controller untuk menghandle logic sementara di dokementasi di jelaskan dengan cara menggunakan fungsi anonim di route.
Aku akan jelaskan cara dari kode di atas bekerja setelah itu aku akan jelaskan apa yang di maksud oleh dokumentasi. Di baris ke 3 dari kode itu menandakan bahwa rute tersebut membutuhkan 2 parameter yaitu id dan hash, bila kamu perhatikan lebih detail email yang di kirim oleh laravel maka kamu akan menyadari bahwa sebenarnya link tersebut berisi 4 hal yaitu id, hash, waktu link tersebut expired dan signature. Nah signature itu digunakan untuk melewati middleware signed
sementara id dan hash akan di handle di VerifyEmailController
. Jika kamu perhatikan di kontroller itu mungkin kamu sadar bahwa kontroller menggunakan EmailVerificationRequest
padahal biasanya menggunakan Request
, EmailVerificationRequest digunakan karena itu adalah form request
bawaan laravel yang akan secara otomatis memvalidasi request yang datang harus menyertakan id
dan hash
.
Mungkin kamu bertanya – tanya bagaimana bisa EmailVerificationRequest
bisa secara otomatis melakukan validasi terhadap parameter id dan hash seperti yang di katakan di dokumentasi, Jawabannya adalah baca lagi dokumentasinya. Di sana di jelaskan bahwa EmailVerificationRequest adalah sebuah Form Request
lebih tepatnya Form Request Validation dan ketika aku klik link yang disediakan laravel aku di arahkan ke halaman dokumentasi Form Request Validation.
Di halaman tersebut aku menemukan informasi ketika membuat sebuah form request validasi maka laravel akan secara default membuat 2 metode pada form request yang kita buat yaitu authorize
dan Rules
, Kemudian di jelaskan juga ketika kita melakukan Type-Hint
request yang kita buat ke sebuah kontroller maka laravel secara otomatis akan melakukan validasi terhadap request yang datang sebelum di proses oleh kontroller. Dengan kata lain metode authorize
dan Rules
akan di jalankan secara otomatis. Sekarang aku rasa kamu paham bagaiman sifat dan perilaku bawaan dari sebuah form request validation, Kita kembali ke EmailVerificationRequest.
Ingat bahwa EmailVerificationRequest itu adalah bawaan dari laravel jadi seharusnya di dalam sana ada metode Authorize
dan Rules
yang sudah otomatis di atur untuk memvalidasi id dan hash, Untuk membuktikan hal tersebut mari kita melihat lebih dalam ke dokumentasinya. Kamu bisa mengunjungi halaman API Documentation
dari laravel dan biar lebih cepat kunjungi saja link ini.
Sekarang kamu harus kembali memeriksa kode di VerifyEmailController
dan cari dari mana asal EmailVerificationRequest, Kamu seharusnya menemukan kode ini use Illuminate\Foundation\Auth\EmailVerificationRequest;
dan memang dari situ form request tersebut berasal. Langkah berikutnya adalah kembali ke halaman API Documentation lalu bernavigasilah ke Illuminate >> Foundation >> Auth lalu pilih Class EmailVerificationRequest.
Di sana di jelaskan dengan detail tentang Class EmailVerificatonRequest, Dia extends dari apa, memiliki Traits apa saja, Properties apa saja dan Methods apa saja. Dan mari fokus ke bagian methods karena kita akan mencari method Authorize
dan Rules
. Di sana ada terlalu banyak methods namun kita akan fokus ke method dari class itu sendiri dan biasanya terletak di akhir list dan tidak ada tanda from
.

Di sana sudah di jelaskan itu metode ngapain aja jadi aku rasa sedikit banyak kamu paham lah ya, Sekarang coba klik authorize()
dan di pojok kanan ada link at line 16. Kalau kamu klik maka kamu akan di arahkan ke source code dari class EmailVerificationRequest dan di sana semua pertanyaan yang mungkin kamu tanyakan terkait bagaimana cara class tersebut otomatis memvalidasi id dan hash seharusnya terjawab.

Coba kamu buka database mu pada tabel users
, maka kamu akan mendapati data yang tadi kamu input waktu melakukan register namun pada kolom email_verified_at
berisi kosong yang menandakan bahwa user tersebut belum melakukan verifikasi email dan cara verifikasi email cukup dengan cari email yang masuk ke akun mu (cari di spam kalau tidak ketemu ya) lalu ikuti instruksi yang ada di email tersebut dan jika berhasil maka kolom email_verified_at
akan berisi data dengan format time_stamp
dan jika kamu coba login dengan akun tersebut maka sekarang kamu sudah