Belajar PHP - Namespace, Errors & Exception
Episode 8 of 23

Belajar PHP - Namespace, Errors & Exception

Menata organisasi kode PHP: namespace dan use untuk menghindari konflik nama, autoloading PSR-4 lewat Composer, lalu menangani kegagalan dengan try/catch/finally, custom exception, dan bagaimana PHP 7+ menyatukan error dan exception lewat ErrorException agar program tidak pernah crash diam-diam.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Saat proyek kecil menjadi besar, dua masalah selalu muncul: konflik nama (dua class bernama User dari dua vendor berbeda) dan kegagalan program (bagaimana menangani database down, file tidak ada, atau input invalid secara terkontrol). Episode 8 menjawab keduanya dengan namespace dan exception handling.

Mengapa ini penting? Namespace adalah alasan ekosistem PHP bisa punya ratusan ribu package di Packagist tanpa saling tabrakan. Sedangkan exception handling adalah pembeda antara aplikasi yang menampilkan stack trace mentah ke pengguna vs aplikasi yang menangani kegagalan dengan anggun. Keduanya adalah keterampilan wajib sebelum kalian menyentuh framework.

Namespace dan use

Namespace adalah "folder" logis untuk class. Convention: namespace mengikuti struktur folder dan penamaan Vendor\Package.

deklarasi namespace
// src/Payment/Gateway.php
namespace App\Payment;
 
class Gateway
{
    public function proses(float $jumlah): bool
    {
        return $jumlah > 0;
    }
}

Kemudian di file lain:

import dengan use
// src/OrderService.php
namespace App\Service;
 
use App\Payment\Gateway;
 
class OrderService
{
    public function __construct(
        private Gateway $gateway,
    ) {}
 
    public function checkout(float $total): bool
    {
        return $this->gateway->proses($total);
    }
}

Tanpa use, kita harus menulis new App\Payment\Gateway(). Konflik nama diselesaikan dengan alias:

Alias untuk konflik nama
use App\Payment\Gateway;
use External\Payment\Gateway as ExternalGateway;

Autoloading PSR-4

Memanggil require manual satu per satu tidak akan bertahan di proyek nyata. Solusinya: autoloading. Dengan PSR-4, PHP tahu cara memuat class hanya berdasarkan nama namespace-nya. Aturan PSR-4: namespace App\ dipetakan ke folder src/, sehingga App\Payment\Gateway otomatis dicari di src/Payment/Gateway.php.

Pendeklarasiannya dilakukan di composer.json (detail lengkap di episode 9):

composer.json (potongan)
{
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    }
  }
}

Setelah itu jalankan composer dump-autoload dan panggil require "vendor/autoload.php"; sekali di entry point. Seluruh class yang dipakai akan dimuat otomatis — inilah yang membuat kode PHP modern bersih dari require_once berserakan.

Note

Autoloading bukan sekadar kenyamanan — ini fondasi ekosistem. Ketika kalian composer require laravel/framework, puluhan package termuat otomatis lewat mekanisme yang sama. Memahami PSR-4 berarti memahami cara kerja semua framework PHP.

Error vs Exception

Sebelum PHP 7, ada dua dunia terpisah: error (warning, notice, fatal) dan exception. Sejak PHP 7, hampir semua error berubah menjadi Throwable yang bisa ditangkap:

Hirarki Throwable
Throwable
├── Error (fatal error: parse, type, dsb.)
│   ├── TypeError
│   ├── ValueError
│   └── ...
└── Exception
    └── RuntimeException, InvalidArgumentException, dsb.

Perbedaan praktis: Error = sesuatu salah dengan kode kalian sendiri (panggil fungsi dengan tipe salah); Exception = kondisi luar yang perlu ditangani (file tidak ada, koneksi gagal).

try/catch/finally

try, catch, finally
<?php
declare(strict_types=1);
 
function bacaFile(string $path): string
{
    if (!is_readable($path)) {
        throw new RuntimeException("File tidak bisa dibaca: $path");
    }
    return file_get_contents($path);
}
 
try {
    $isi = bacaFile("/tmp/konfigurasi.txt");
    echo $isi;
} catch (RuntimeException $e) {
    echo "Gagal membaca: " . $e->getMessage() . "\n";
} catch (Throwable $e) {
    echo "Terjadi kegagalan tak terduga\n";
} finally {
    echo "Block ini selalu dijalankan.\n";
}
  • try — blok yang dipantau.
  • catch — penanganan per tipe exception; urut dari paling spesifik ke umum (Throwable terakhir).
  • finally — selalu dieksekusi, baik sukses maupun gagal; tempat ideal untuk menutup koneksi/file.

Custom Exception

Exception khusus membuat penanganan lebih ekspresif dan log lebih informatif:

Custom exception
namespace App\Exception;
 
use RuntimeException;
 
class PaymentFailedException extends RuntimeException
{
    public static function insufficientFunds(float $butuh, float $punya): self
    {
        return new self(
            sprintf("Saldo tidak cukup: butuh %s, punya %s", $butuh, $punya)
        );
    }
}

Lalu tangkap secara spesifik:

Menangkap custom exception
use App\Exception\PaymentFailedException;
 
try {
    $payment->proses(100000);
} catch (PaymentFailedException $e) {
    log_error($e->getMessage());
    return response()->json(["error" => "Pembayaran gagal"], 402);
}

Pola named constructor (self::insufficientFunds()) membuat pemanggilan ekspresif sekaligus memusatkan pesan error di satu tempat.

Global Error & Exception Handler

Untuk aplikasi web, pasang handler global agar error tidak pernah bocor mentah ke pengguna (detail keamanan di episode 17):

Handler global
set_exception_handler(function (Throwable $e): void {
    error_log($e->getMessage());
    http_response_code(500);
    echo "Terjadi kesalahan server.";
});
 
set_error_handler(function (int $level, string $message): bool {
    throw new ErrorException($message, 0, $level);
});

Dengan set_error_handler yang melempar ErrorException, semua warning PHP klasik ikut menjadi exception yang bisa ditangkap — inilah yang dimaksud "PHP 7+ menyatukan error dan exception".

Warning

Jangan menangkap exception lalu diam saja (catch (Throwable $e) {}). Paling sedikit log exception-nya dan beri respons yang jelas ke pengguna. Error yang ditelan adalah bug yang menunggu ledakan di waktu paling buruk.

Common Pitfalls

  • Lupa declare(strict_types=1)TypeError tidak muncul dan bug tersembunyi.
  • Menangkap Exception tapi fungsi melempar Error — gunakan Throwable bila ingin menangkap semua.
  • Exception untuk kontrol alur — jangan pakai try/catch untuk if/else biasa; exception itu mahal dan hanya untuk kondisi luar biasa.
  • Namespace tidak sesuai folder — autoload gagal; pastikan PSR-4 mapping persis.

Penutup

Inti yang harus dibawa pulang:

  • Namespace + use menghindari konflik nama; autoloading PSR-4 menghilangkan require manual.
  • Throwable menyatukan Error (bug kode) dan Exception (kondisi luar) sejak PHP 7.
  • Gunakan try/catch/finally dengan urutan catch paling spesifik ke umum.
  • Buat custom exception dengan named constructor agar pesan error konsisten.
  • Pasang global handler agar error tidak pernah bocor ke pengguna.

Di episode 9 selanjutnya kita mengoperasikan fondasi ekosistem: Composer & Autoloadingcomposer init/install/require, memahami composer.json dan composer.lock, semantic versioning, hingga composer audit untuk keamanan dependensi. Di sini kalian mulai membangun proyek seperti engineer profesional.

Belajar PHP - Namespace, Errors & Exception | Belajar PHP