Lewati ke konten utama

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 melempar AuthorizationException jika gagal.

  • authorizeForUser($user, string $ability, $arguments = [])
    Mirip authorize, tapi untuk user selain auth()->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

  1. 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).

  2. Form Requests untuk Validasi
    Alih‑alih menggunakan trait ValidatesRequests, Laravel menganjurkan penggunaan Form Request classes (php artisan make:request), yang mengenkapsulasi rule validasi dan otorisasi via authorize() method di form request itu sendiri (Laravel).

  3. 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, sehingga AuthorizesRequests 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:

MethodContoh HasilKeterangan
asset()https://ex.com/css/app.cssAuto HTTPS untuk CSS/JS
url()https://ex.com/checkoutLink absolute secure
route()https://ex.com/dashboardNamed route dengan HTTPS
mix()https://ex.com/build/app.jsKompatibel dengan Laravel Mix

Analogi untuk Pemula:

  1. HTTPS 🛡️ -> Seperti paket yang dikirim dengan armored truck
  2. Immutable Dates 🗓️ -> Foto kopi vs tulisan di whiteboard
  3. Strict Mode 🚨 -> Sistem CCTV di gudang barang berharga
  4. Vite Prefetch 🚂 -> Kereta yang mengangkut semua barang sekaligus