Namespace & Autoloading

Saat project PHP-mu masih kecil (5–10 file), kamu bisa require file satu per satu. Tapi bayangkan project Laravel dengan ratusan class — bagaimana cara mengorganisasinya tanpa konflik nama dan tanpa menulis ratusan require?

Jawabnya: Namespace + Autoloading.

1. Masalah Tanpa Namespace

Tanpa namespace, semua class berada di "ruang global" yang sama. Ini bermasalah saat dua class punya nama sama:

<?php

// ❌ KONFLIK! Dua class bernama "User" di project yang sama

// file: models/User.php
class User  // User untuk database
{
    public function save(): void { /* ... */ }
}

// file: auth/User.php  
class User  // User untuk autentikasi — FATAL ERROR!
{
    public function login(): void { /* ... */ }
}

// PHP akan error: Cannot declare class User, 
// because the name is already in use

2. Namespace — Ruang Nama

Namespace adalah cara memberi "alamat" unik ke setiap class, seperti folder di file system.

<?php
// file: src/Models/User.php
namespace App\Models;

class User
{
    public string $name;
    public string $email;

    public function save(): string
    {
        return "User {$this->name} disimpan ke database";
    }
}
<?php
// file: src/Auth/User.php
namespace App\Auth;

class User
{
    public string $username;

    public function login(): string
    {
        return "{$this->username} berhasil login";
    }
}
<?php
// file: index.php — Menggunakan kedua class

// Cara 1: Nama lengkap (Fully Qualified Name)
$dbUser = new \App\Models\User();
$authUser = new \App\Auth\User();

// Cara 2: Import dengan 'use' (lebih rapi!)
use App\Models\User;
use App\Auth\User as AuthUser; // Alias untuk menghindari konflik

$dbUser = new User();           // App\Models\User
$authUser = new AuthUser();     // App\Auth\User
Analogi Namespace

Namespace seperti alamat rumah. Ada banyak orang bernama "Budi" di Indonesia, tapi hanya ada satu "Budi di Jl. Merdeka No. 10, Jakarta". Namespace adalah alamat yang membuat setiap class unik.


3. Konvensi Penamaan: PSR-4

PHP community punya standar bernama PSR-4 yang memetakan namespace ke struktur folder:

Namespace:     App\Models\User
                ↓     ↓      ↓
Folder:        src/Models/User.php

Aturan PSR-4:

AturanContoh
1 class per fileUser.php hanya berisi class User
Nama file = nama classProduct.phpclass Product
Namespace = struktur folderApp\Servicessrc/Services/
PascalCase untuk classUserService, bukan userservice

Contoh Struktur Project

my-php-app/
├── src/
│   ├── Models/
│   │   ├── User.php          → App\Models\User
│   │   ├── Product.php       → App\Models\Product
│   │   └── Order.php         → App\Models\Order
│   ├── Services/
│   │   ├── AuthService.php   → App\Services\AuthService
│   │   └── PaymentService.php → App\Services\PaymentService
│   └── Controllers/
│       ├── HomeController.php → App\Controllers\HomeController
│       └── ApiController.php  → App\Controllers\ApiController
├── vendor/                    → Dependencies dari Composer
├── composer.json
└── index.php

4. Autoloading — Otomatis Memuat Class

Tanpa autoloading, kamu harus require setiap file:

<?php
// ❌ Tanpa autoloading: require semua file satu per satu
require 'src/Models/User.php';
require 'src/Models/Product.php';
require 'src/Models/Order.php';
require 'src/Services/AuthService.php';
require 'src/Services/PaymentService.php';
// ... dan seterusnya untuk RATUSAN file 😩

Dengan Composer autoloading, PHP otomatis menemukan file yang tepat:

<?php
// ✅ Dengan autoloading: cukup satu baris!
require 'vendor/autoload.php';

use App\Models\User;
use App\Services\AuthService;

$user = new User();           // PHP otomatis cari src/Models/User.php
$auth = new AuthService();    // PHP otomatis cari src/Services/AuthService.php

Setup Autoloading di composer.json

{
    "name": "belajar/php-app",
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

Konfigurasi di atas mengatakan: "Setiap class yang dimulai dengan App\, cari di folder src/."

Setelah menambahkan config, jalankan:

composer dump-autoload
Penting!

Setiap kali kamu menambah namespace baru di composer.json, jalankan composer dump-autoload agar autoloader diperbarui.


5. Contoh Lengkap: Mini Project

Berikut contoh project kecil dengan namespace dan autoloading:

File: src/Models/Product.php

<?php
declare(strict_types=1);

namespace App\Models;

class Product
{
    public function __construct(
        private string $name,
        private int $price,
        private int $stock = 0,
    ) {}

    public function getName(): string
    {
        return $this->name;
    }

    public function getFormattedPrice(): string
    {
        return 'Rp ' . number_format($this->price, 0, ',', '.');
    }

    public function isAvailable(): bool
    {
        return $this->stock > 0;
    }
}

File: src/Services/ProductService.php

<?php
declare(strict_types=1);

namespace App\Services;

use App\Models\Product;

class ProductService
{
    /** @var Product[] */
    private array $products = [];

    public function add(Product $product): void
    {
        $this->products[] = $product;
    }

    public function getAvailable(): array
    {
        return array_filter(
            $this->products,
            fn(Product $p) => $p->isAvailable()
        );
    }

    public function count(): int
    {
        return count($this->products);
    }
}

File: index.php

<?php
declare(strict_types=1);

require 'vendor/autoload.php';

use App\Models\Product;
use App\Services\ProductService;

$service = new ProductService();

$service->add(new Product('Keyboard Mechanical', 750000, 10));
$service->add(new Product('Mouse Wireless', 250000, 0));
$service->add(new Product('Monitor 24"', 2500000, 3));

echo "Total produk: " . $service->count() . "\n";
echo "Produk tersedia: " . count($service->getAvailable()) . "\n";

foreach ($service->getAvailable() as $product) {
    echo "- {$product->getName()} ({$product->getFormattedPrice()})\n";
}

// Output:
// Total produk: 3
// Produk tersedia: 2
// - Keyboard Mechanical (Rp 750.000)
// - Monitor 24" (Rp 2.500.000)

6. Namespace di Laravel

Di Laravel, struktur namespace sudah dibuat otomatis:

app/
├── Http/
│   ├── Controllers/     → App\Http\Controllers\
│   └── Middleware/       → App\Http\Middleware\
├── Models/              → App\Models\
├── Services/            → App\Services\ (kamu buat sendiri)
└── Providers/           → App\Providers\

Setiap kali kamu menjalankan php artisan make:model Product, Laravel otomatis:

  1. Membuat file di app/Models/Product.php
  2. Menambahkan namespace App\Models;
  3. Autoload sudah dikonfigurasi di composer.json
Ingat Pola Ini
namespace = alamat class
use = import class dari alamat lain
autoload = PHP otomatis cari file berdasarkan alamat

Tiga konsep ini saling terkait dan merupakan fondasi project PHP modern.


Latihan

  1. Buat struktur folder: src/Models/, src/Services/, lalu buat class Student di Models dan StudentService di Services
  2. Setup composer.json dengan autoloading PSR-4 yang memetakan App\\ ke src/
  3. Jalankan composer dump-autoload
  4. Buat index.php yang menggunakan kedua class tanpa require manual
  5. Tambahkan class Teacher di src/Models/ dan gunakan di index.php — pastikan autoloading bekerja

Selanjutnya

Kamu sudah bisa mengorganisasi kode seperti developer profesional. Lanjut ke Design Patterns → untuk mengenal pola-pola desain yang paling sering dipakai di Laravel.

Troubleshooting Autoloading

Kalau setelah memindahkan file atau membuat class baru Laravel malah memunculkan error, lanjut ke: