Best Partice Laravel
dont use auth()->user() in action layer. cause cant use in console ,migration etc.
Gate::authoreized() gunakan di method authorized FormRequest supaya gate dulu dipanggil sebelum rules dijalankan. Untuk method index() pada controller anda bisa gunakan Gate disana karena bisa jadi tidak ada FormRequest pada index().
Menjelaskan Fungsi Traits pada Controller
Pengguna ingin tahu tentang penggunaan AuthorizesRequests
dan ValidatesRequests
dalam Controller yang diturunkan dari BaseController. Traits tersebut di Laravel digunakan untuk menangani otorisasi dan validasi otomatis dalam metode controller tanpa memerlukan kode tambahan, mempermudah proses tersebut. Mengenai kekurangan BaseController di proyek Nuno Maduro, kemungkinan dia memilih untuk tidak menggunakan BaseController agar menghindari dependensi atau karena alternative lainnya lebih sesuai dengan desain proyek.
Menggunakan Traits pada Controller dan Pendekatan Nuno Maduro
Traits seperti AuthorizesRequests
dan ValidatesRequests
memungkinkan controller Laravel untuk menangani otorisasi dan validasi. Nuno Maduro tidak menggunakan BaseController dalam proyeknya karena pendekatannya menggunakan kelas-kelas stateless atau perintah konsol, bukan controller HTTP biasa. Penggunaan ini menghindari kebutuhan untuk traits tersebut. Untuk lebih memahami, saya akan merujuk pada dokumentasi Laravel dan dokumentasi paket dari Nuno Maduro, serta sumber lain seperti Laracasts atau StackOverflow jika diperlukan.
Selesai berpikir selama 22 detik
Ringkasan
Trait AuthorizesRequests
dan ValidatesRequests
di Laravel memberikan helper methods untuk otorisasi policy (authorize
, authorizeForUser
, authorizeResource
) dan validasi form (validate
, $request->validate()
) dalam controller tanpa boilerplate (Laravel, Laravel News). Namun sejak Laravel 11, Base Controller di app/Http/Controllers/Controller.php
disederhanakan—tidak lagi meng-use
kedua trait ini secara otomatis—agar developer dapat memilih sendiri di mana otorisasi dan validasi diperlukan (Securing Laravel, Laravel). Karena itu, banyak paket atau boilerplate dari Nuno Maduro (yang sering memperkenalkan “action” pattern dan Form Requests) tidak mengandalkan Base Controller bawaan Laravel, melainkan membuat class atau action terpisah untuk logika bisnis—menjaga controller tetap tipis dan fokus (travismhayes.com).
1. Fungsi AuthorizesRequests
Trait ini (terletak di Illuminate\Foundation\Auth\Access\AuthorizesRequests
) menyediakan method:
-
authorize(string $ability, $arguments = [])
Memeriksa Gate atau Policy dengan melemparAuthorizationException
jika gagal. -
authorizeForUser($user, string $ability, $arguments = [])
Miripauthorize
, tapi untuk user selainauth()->user()
. -
authorizeResource(string $model, string $parameter = null)
Mendaftarkan otorisasi otomatis pada resource controller (mis.index
,show
,update
) (Laravel).
Dengan trait ini, Anda bisa menulis di controller:
public function update(Post $post)
{
$this->authorize('update', $post);
// ...logic update
}
Tanpa trait, Anda harus memanggil Gate::authorize()
atau helper lain di setiap metode.
2. Fungsi ValidatesRequests
Trait ini (di Illuminate\Foundation\Validation\ValidatesRequests
) memberikan method:
-
validate(Request $request, array $rules, array $messages = [], array $customAttributes = [])
Validasi data dan otomatis redirect kembali dengan error jika gagal. -
Alternatif, Anda juga dapat memanggil
$request->validate($rules)
(Laravel News).
Contoh penggunaan:
public function store(Request $request)
{
$data = $this->validate($request, [
'title' => 'required|string|max:255',
'body' => 'required',
]);
Post::create($data);
}
Tanpa trait, Anda harus meng-use
Validator
facade secara manual dan handle error response sendiri.
3. Base Controller & Perubahan di Laravel 11
Sebelum Laravel 11, file app/Http/Controllers/Controller.php
umumnya tampak seperti:
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
abstract class Controller extends BaseController
{
use AuthorizesRequests, ValidatesRequests;
}
Sejak Laravel 11, Controller disederhanakan menjadi:
namespace App\Http\Controllers;
abstract class Controller
{
//
}
Trait AuthorizesRequests
dan ValidatesRequests
tidak lagi di-use
secara otomatis (Laravel). Jika diperlukan, developer harus memasukkannya sendiri ke controller terkait (Securing Laravel).
4. Kenapa Nuno Maduro Tidak Menggunakan Base Controller
-
Pattern “Action” & Form Requests
Nuno Maduro mempopulerkan action pattern (“thin controllers”)—logika bisnis ditempatkan di class action terpisah—sehingga controller hanya mendelegasikan ke action tersebut tanpa butuh helper trait (travismhayes.com). -
Form Requests untuk Validasi
Alih‑alih menggunakan traitValidatesRequests
, Laravel menganjurkan penggunaan Form Request classes (php artisan make:request
), yang mengenkapsulasi rule validasi dan otorisasi viaauthorize()
method di form request itu sendiri (Laravel). -
Target Laravel 11+
Banyak boilerplate atau paket terbaru (oleh Nuno) dirancang untuk Laravel 11 atau lebih baru, di mana Base Controller tidak lagi memasukkan trait secara default. Developer “menyisipkan” kebutuhan otorisasi/validasi hanya di controller yang memerlukannya, bukan global (Laravel).
Dengan demikian, absennya use AuthorizesRequests, ValidatesRequests
di projek Nuno Maduro sering kali karena ia:
-
Menggunakan Form Request untuk validasi (
ValidatesRequests
tidak diperlukan). -
Menggunakan action classes dan kebijakan (
Policy
) langsung via Gate, sehinggaAuthorizesRequests
trait juga tidak selalu dipakai di controller.
Referensi Utama
-
Security Tip: Laravel 11 Controller Simplification (Stephen Rees‑Carter) (Securing Laravel)
-
Laravel 11 Release Notes: Base Controller Changes (Laravel)
-
Laravel Docs – Authorization (5.1) (Laravel)
-
Laravel News – Validation Quickstart (Laravel)
-
Laravel Docs – ValidatesRequests Trait (Laravel News)
-
Best Practice: Thin Controllers with Actions (Travis Hayes referencing Nuno Maduro) (travismhayes.com)
-
Using a trait in all controllers (Laracasts) (Laracasts)
-
Controller ValidateRequests error on StackOverflow (stackoverflow.com)
{
"preset": "laravel",
"notPath": [
"tests/TestCase.php",
"app/Console/Kernel.php",
"app/Exceptions/Handler.php",
"intelephense_helper.php",
"bootstrap/app.php"
],
"exclude": ["app/Http/Middleware"],
"rules": {
"array_push": true,
"backtick_to_shell_exec": true,
"date_time_immutable": true,
"declare_strict_types": true,
"lowercase_keywords": true,
"lowercase_static_reference": true,
"final_class": true,
"final_internal_class": true,
"final_public_method_for_abstract_class": true,
"fully_qualified_strict_types": true,
"global_namespace_import": {
"import_classes": false,
"import_constants": true,
"import_functions": true
},
"mb_str_functions": true,
"modernize_types_casting": true,
"new_with_parentheses": false,
"no_superfluous_elseif": true,
"no_useless_else": true,
"no_multiple_statements_per_line": true,
"ordered_class_elements": {
"order": [
"use_trait",
"case",
"constant",
"constant_public",
"constant_protected",
"constant_private",
"property_public",
"property_protected",
"property_private",
"construct",
"destruct",
"magic",
"phpunit",
"method_abstract",
"method_protected",
"method_protected_static",
"method_public",
"method_public_static",
"method_private",
"method_private_static"
],
"sort_algorithm": "none"
},
"ordered_interfaces": true,
"ordered_traits": true,
"protected_to_private": true,
"self_accessor": true,
"self_static_accessor": true,
"strict_comparison": true,
"visibility_required": true
}
}
<?php
declare(strict_types=1);
namespace App\Providers;
use Carbon\CarbonImmutable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Vite;
use Illuminate\Support\ServiceProvider;
final class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
$this->configureCommands();
$this->configureModels();
$this->configureDates();
$this->configureUrls();
$this->configureVite();
}
/**
* Configure the application's commands.
*/
private function configureCommands(): void
{
DB::prohibitDestructiveCommands(
$this->app->isProduction(),
);
}
/**
* Configure the application's dates.
*/
private function configureDates(): void
{
Date::use(CarbonImmutable::class);
}
/**
* Configure the application's models.
*/
private function configureModels(): void
{
Model::unguard();
Model::shouldBeStrict();
}
/**
* Configure the application's URLs.
*/
private function configureUrls(): void
{
URL::forceScheme('https');
}
/**
* Configure the application's Vite instance.
*/
private function configureVite(): void
{
Vite::useAggressivePrefetching();
}
}
Berikut implementasi dengan contoh lebih detail dalam komentar kode, termasuk contoh variabel dan efek metode HTTPS pada helper Laravel:
/**
* 🔐 Memaksa HTTPS untuk SEMUA URL generated (termasuk asset(), url(), route())
* Contoh:
* - asset('css/app.css') => https://example.com/css/app.css
* - url('/checkout') => https://example.com/checkout
*
* Studi Kasus Cocok:
* - Production environment dengan SSL
* - Aplikasi banking yang memproses pembayaran
*
* Studi Kasus Tidak Cocok:
* - Local development tanpa sertifikat SSL (akan error)
*/
private function configureUrls(): void
{
URL::forceScheme('https');
}
/**
* 📅 Contoh Penggunaan CarbonImmutable:
*
* $tanggalA = Date::now(); // 2023-10-01 00:00:00
* $tanggalB = $tanggalA->addDays(3);
*
* Hasil:
* - $tanggalA tetap 2023-10-01 00:00:00 🎯
* - $tanggalB menjadi 2023-10-04 00:00:00
*
* Studi Kasus Cocok:
* - Sistem payroll yang tidak boleh ada perubahan tanggal retroaktif
* - Aplikasi reservasi tiket pesawat
*/
private function configureDates(): void
{
Date::use(CarbonImmutable::class);
}
/**
* 🔒 Contoh Mass Assignment dengan unguard():
*
* User::create(['role' => 'admin', 'name' => 'Hacker']); // 🆗 DIizinkan
*
* Contoh Lazy Loading di strict mode:
*
* $posts = Post::all();
* foreach ($posts as $post) {
* echo $post->author->name; // 🚨 Throw LazyLoadingException
* }
*/
private function configureModels(): void
{
Model::unguard();
Model::shouldBeStrict();
}
/**
* 🚫 Contoh Efek prohibitDestructiveCommands():
*
* php artisan migrate:fresh
* ⚠️ Error: Database destructive commands are prohibited
*
* Studi Kasus Cocok:
* - Server production e-commerce dengan 1M+ transaksi
* - Database kesehatan pasien rumah sakit
*/
private function configureCommands(): void
{
DB::prohibitDestructiveCommands($this->app->isProduction());
}
/**
* 🚀 Contoh Prefetching Vite:
*
* - Akan memuat SEMUA file di resources/js/components/*.vue
* - Saat buka halaman Home, semua komponen sudah ter-cache
*
* Studi Kasus Cocok:
* - Dashboard analytics dengan 50+ chart components
* - Aplikasi CRM dengan banyak modul
*
* Studi Kasus Tidak Cocok:
* - Landing page dengan 1 file CSS dan 2 gambar
*/
private function configureVite(): void
{
Vite::useAggressivePrefetching();
}
Contoh Lengkap Implementasi di Controller:
class OrderController extends Controller
{
public function checkout()
{
// 🔐 Contoh HTTPS URL
$paymentUrl = url('/payment'); // otomatis https://...
// 📅 Contoh Manipulasi Tanggal
$orderDate = Date::now();
$dueDate = $orderDate->addDays(7); // Tidak mengubah $orderDate
// 🔒 Contoh Mass Assignment
Order::create($request->all()); // Aman karena unguard()?
// ❗️ Tetap perlu validasi input di controller!
return view('checkout', [
'dueDate' => $dueDate->format('d F Y'),
'cssUrl' => asset('css/checkout.css') // https://...
]);
}
}
Output Hasil:
<!-- Contoh URL yang di-generate -->
<link href="https://example.com/css/checkout.css" rel="stylesheet">
<!-- Contoh Tampilan Tanggal -->
<p>Batas Pembayaran: 12 Oktober 2023</p>
<!-- Contoh Error di Development -->
@error
[Illuminate\Database\LazyLoadingException]
Attempted to lazy load [author] on model [App\Models\Post]
@enderror
Skema Kerja HTTPS pada Berbagai Helper:
Method | Contoh Hasil | Keterangan |
---|---|---|
asset() | https://ex.com/css/app.css | Auto HTTPS untuk CSS/JS |
url() | https://ex.com/checkout | Link absolute secure |
route() | https://ex.com/dashboard | Named route dengan HTTPS |
mix() | https://ex.com/build/app.js | Kompatibel dengan Laravel Mix |
Analogi untuk Pemula:
- HTTPS 🛡️ -> Seperti paket yang dikirim dengan armored truck
- Immutable Dates 🗓️ -> Foto kopi vs tulisan di whiteboard
- Strict Mode 🚨 -> Sistem CCTV di gudang barang berharga
- Vite Prefetch 🚂 -> Kereta yang mengangkut semua barang sekaligus