Begitu aplikasi Warung Bu Tini tumbuh, class-nya pindah ke file masing-masing, dan nama yang sama mulai bentrok. Namespace memberi tiap class nama lengkap, dan autoloading membuat PHP menemukan file class itu sendiri, tanpa require satu per satu. Bayangin alamat surat. Ada banyak "Jalan Melati" di Indonesia, jadi alamat lengkapnya ditulis dengan kota: "Jalan Melati, Bandung" beda dengan "Jalan Melati, Solo". Namespace adalah nama kotanya, dan PSR-4 adalah aturan pos yang mengubah alamat itu jadi rak tempat suratnya disimpan.
🧪 Tebakan cepat: class
App\Services\Kasirmenulispublic function total(Menu $menu, ...)tapi lupause App\Models\Menu;. Laluindex.phpmemanggilnya dengan objectApp\Models\Menu. PHP menganggapMenudi situ class yang mana? Tebak dulu, jawabannya ada di bagian "use: memanggil dengan nama pendek".
Namespace: nama lengkap untuk class
Warung memakai library pengiriman yang juga punya class Menu. Tanpa namespace, dua class bernama sama gak bisa hidup bersama:
Fatal error: Cannot redeclare class Menu (previously declared in /var/www/warung/src/Models/Menu.php:2) in /var/www/warung/vendor/ojol/api/src/Menu.php on line 2
Dengan namespace, tiap file menyebut "kota"-nya di baris pertama setelah <?php:
<?php
// src/Models/Menu.php
namespace App\Models;
class Menu
{
public function __construct(public string $nama, public int $harga) {}
}
namespace App\Models;membuat nama lengkap class di file iniApp\Models\Menu. Milik library jadiOjol\Api\Menu. Dua nama yang beda, gak bentrok lagi.- Pemisahnya backslash
\, bukan titik atau garis miring. - Deklarasi
namespaceharus jadi perintah pertama di file. Adaechodi atasnya:Namespace declaration statement has to be the very first statement or after any declare call in the script. Menu::classberisi nama lengkapnya sebagai string:"App\Models\Menu".
use: memanggil dengan nama pendek
<?php
// src/Services/Kasir.php
namespace App\Services;
use App\Models\Menu;
class Kasir
{
public function total(Menu $menu, int $jumlah): int
{
return $menu->harga * $jumlah;
}
}
- Di dalam
namespace App\Services, nama pendekMenudicari di namespace itu sendiri:App\Services\Menu. use App\Models\Menu;bilang ke PHP: di file ini,MenuberartiApp\Models\Menu.- Tanpa baris
useitu,Menudi parameter dibaca sebagaiApp\Services\Menu. Itu jawaban tebakannya. Hasilnya:
Fatal error: Uncaught TypeError: App\Services\Kasir::total(): Argument #1 ($menu) must be of type App\Services\Menu, App\Models\Menu given
- Dua class dengan nama pendek sama di satu file? Beri alias dengan
as:use Ojol\Api\Menu as MenuOjol;. Tanpa alias:Cannot use Ojol\Api\Menu as Menu because the name is already in use. - Class bawaan PHP tinggal di namespace global. Di dalam namespace,
new DateTime()dicari sebagaiApp\Services\DateTimedan gagal denganClass "App\Services\DateTime" not found. Tulisnew \DateTime()atauuse DateTime;.
PSR-4: namespace jadi folder
PSR-4 adalah standar yang memetakan nama class ke lokasi file. Aturannya ditulis di composer.json:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
| Nama class | Awalan App\ diganti src/ |
File |
|---|---|---|
App\Models\Menu |
src/ + Models\Menu |
src/Models/Menu.php |
App\Services\Kasir |
src/ + Services\Kasir |
src/Services/Kasir.php |
$ composer dump-autoload
Generating autoload files
Generated autoload files
Lalu index.php, file yang dibuka pertama kali:
<?php
require __DIR__ . "/vendor/autoload.php";
use App\Models\Menu;
use App\Services\Kasir;
$nasi = new Menu("Nasi Goreng", 15000);
echo (new Kasir())->total($nasi, 2) . "\n"; // 30000
"App\\"ditulis dengan dua backslash karena di JSON backslash harus di-escape. Artinya awalanApp\.composer dump-autoloadmenulis peta itu kevendor/composer/dan membuatvendor/autoload.php.require __DIR__ . "/vendor/autoload.php";cukup sekali, di file yang pertama dijalankan. Setiap kali class yang belum dikenal dipakai, autoloader menghitung path-nya dengan aturan di atas dan me-requirefile itu.- Satu file berisi satu class, nama file sama persis dengan nama class-nya (
Menu.php), dan nama folder sama persis dengan bagian namespace-nya (Models, bukanModel). Di server Linux, huruf besar-kecil di nama folder juga dibedakan.
Kalau file-nya gak ketemu di path itu, atau vendor/autoload.php lupa di-require, hasilnya sama:
Fatal error: Uncaught Error: Class "App\Models\Menu" not found in /var/www/warung/index.php:7
💡 Kapan perlu composer dump-autoload
- Wajib setelah mengubah bagian
autoloaddicomposer.json, misalnya menggantisrc/jadiapp/. Sebelum dump, autoloader masih memakai peta lama. - File class baru di folder yang sudah dipetakan PSR-4 (misalnya
src/Models/Pesanan.php) langsung ketemu tanpa dump: path-nya dihitung saat class itu dipakai. composer dump-autoload -omembuat daftar semua class sekaligus (classmap), sedikit lebih cepat untuk server produksi.- Laravel memakai aturan yang sama:
"App\\": "app/", jadiApp\Models\Usertinggal diapp/Models/User.php.
⚠️ Jebakan yang sering ketemu
- Lupa
use. Nama pendek dicari di namespace file itu sendiri, jadiMenudiApp\ServicesjadiApp\Services\Menu. - Folder atau nama file gak cocok dengan namespace.
src/Model/Menu.phpuntukApp\Models\Menugak pernah ketemu:Class "App\Models\Menu" not found. - Lupa
require "vendor/autoload.php". Tanpa itu gak ada autoloader sama sekali. - Banyak namespace di satu file. PHP sebenarnya mengizinkan beberapa deklarasi
namespacedalam satu file, tapi PSR-4 mengharuskan satu file berisi satu class dengan satu namespace. Ikuti aturan PSR-4, dan pecah ke file masing-masing.
TL;DR: namespace App\Models; di baris pertama file memberi class nama lengkap (App\Models\Menu), jadi class bernama sama dari library lain gak bentrok. use App\Models\Menu; membuat nama pendek Menu menunjuk ke sana (tanpa use, PHP mencarinya di namespace file itu sendiri), as memberi alias, dan class bawaan ditulis \DateTime. PSR-4 memetakan namespace ke folder: dengan "App\\": "src/" di composer.json, App\Models\Menu ada di src/Models/Menu.php. Jalankan composer dump-autoload setelah mengubah autoload, require "vendor/autoload.php" sekali, dan kalau path-nya gak cocok, PHP berhenti dengan Class "App\Models\Menu" not found.