Setiap aplikasi, sesederhana apapun, bisa mengalami error โ koneksi database gagal, file tidak ditemukan, input tidak sesuai format, dan banyak lagi. PHP menyediakan dua mekanisme untuk menangani situasi ini: Error (kesalahan tingkat PHP) dan Exception (kondisi luar biasa yang dilempar dan bisa ditangkap). Memahami keduanya sangat penting untuk membangun aplikasi yang robust dan mudah di-debug.
Jenis-Jenis Error di PHP
PHP memiliki beberapa level error, di antaranya:
- E_ERROR โ error fatal, eksekusi script berhenti.
- E_WARNING โ peringatan, script tetap berjalan.
- E_NOTICE โ pemberitahuan ringan (misal: variabel belum didefinisi).
- E_DEPRECATED โ fungsi yang sudah usang digunakan.
- E_PARSE โ error sintaks, script tidak bisa dijalankan.
Mengatur Tampilan Error
Di lingkungan pengembangan (development), tampilkan semua error. Di produksi, sembunyikan dari user tapi catat ke log:
<?php
// Untuk environment development
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Untuk environment production
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', '/path/to/error.log');
error_reporting(E_ALL);
Lebih baik lagi, atur ini di file php.ini atau .htaccess dan gunakan variabel environment untuk membedakan mode development dan production.
Blok try-catch Dasar
Exception ditangkap menggunakan blok try-catch:
<?php
function bagi(int $a, int $b): float
{
if ($b === 0) {
throw new InvalidArgumentException("Tidak bisa membagi dengan nol!");
}
return $a / $b;
}
try {
$hasil = bagi(10, 2);
echo "10 / 2 = $hasil\n"; // 10 / 2 = 5
$hasil = bagi(10, 0); // Ini akan melempar exception
echo "Baris ini tidak akan dieksekusi";
} catch (InvalidArgumentException $e) {
echo "Error: " . $e->getMessage() . "\n";
echo "Di file: " . $e->getFile() . " baris " . $e->getLine();
}
Menangkap Beberapa Jenis Exception
Kamu bisa memiliki beberapa blok catch untuk menangani jenis exception yang berbeda:
<?php
function prosesFile(string $path): string
{
if (!file_exists($path)) {
throw new RuntimeException("File tidak ditemukan: $path");
}
$konten = file_get_contents($path);
if ($konten === false) {
throw new RuntimeException("Gagal membaca file: $path");
}
if (strlen($konten) === 0) {
throw new LengthException("File kosong: $path");
}
return $konten;
}
try {
$isi = prosesFile('/data/laporan.txt');
echo "Konten: $isi";
} catch (LengthException $e) {
echo "File kosong: " . $e->getMessage();
} catch (RuntimeException $e) {
echo "Error runtime: " . $e->getMessage();
} catch (\Throwable $e) {
// Menangkap semua error dan exception yang tidak tertangani
echo "Error tidak terduga: " . $e->getMessage();
}
Di PHP 8, gunakan \Throwable (bukan \Exception) sebagai fallback untuk menangkap semua jenis error dan exception.
Blok finally
Blok finally selalu dieksekusi, baik ada exception maupun tidak โ berguna untuk membersihkan resource:
<?php
function bacaFile(string $path): void
{
$handle = fopen($path, 'r');
if ($handle === false) {
throw new RuntimeException("Tidak bisa membuka file.");
}
try {
while (($baris = fgets($handle)) !== false) {
echo $baris;
}
} finally {
// Selalu tutup file meski ada exception
fclose($handle);
echo "\nFile telah ditutup.";
}
}
Membuat Custom Exception
Untuk aplikasi yang lebih terstruktur, buat kelas exception sendiri:
<?php
// Definisi custom exception
class DatabaseException extends RuntimeException
{
private string $query;
public function __construct(string $pesan, string $query = '', int $kode = 0, ?\Throwable $sebelumnya = null)
{
$this->query = $query;
parent::__construct($pesan, $kode, $sebelumnya);
}
public function getQuery(): string
{
return $this->query;
}
}
class ValidationException extends \InvalidArgumentException
{
private array $errors;
public function __construct(array $errors)
{
$this->errors = $errors;
parent::__construct("Validasi gagal: " . implode(', ', $errors));
}
public function getErrors(): array
{
return $this->errors;
}
}
// Penggunaan
try {
throw new ValidationException(['Nama wajib diisi', 'Email tidak valid']);
} catch (ValidationException $e) {
foreach ($e->getErrors() as $error) {
echo "- $error\n";
}
}
Set Error Handler Global
Untuk menangkap error PHP (bukan exception) secara global dan mengubahnya menjadi exception:
<?php
// Ubah semua error menjadi ErrorException agar bisa ditangkap dengan try-catch
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool {
throw new \ErrorException($errstr, $errno, 0, $errfile, $errline);
});
// Tangkap exception yang tidak tertangkap
set_exception_handler(function (\Throwable $e): void {
error_log("Uncaught Exception: " . $e->getMessage() . " in " . $e->getFile());
// Tampilkan halaman error yang ramah pengguna
http_response_code(500);
echo "Terjadi kesalahan. Tim kami sedang menangani masalah ini.";
});
Kesimpulan
Penanganan error dan exception yang baik membuat aplikasi PHP kamu lebih robust, mudah di-debug, dan memberikan pengalaman yang lebih baik bagi pengguna. Gunakan blok try-catch-finally untuk menangani kondisi luar biasa, buat custom exception untuk domain-specific error, dan selalu bedakan antara tampilan error di lingkungan development dan production. Dengan pendekatan ini, bug lebih mudah ditemukan dan aplikasi bisa gagal dengan anggun (fail gracefully).