Error Handling حرفهای در PHP — Exception، try-catch و Laravel
خطا در production اجتنابناپذیر است — پرداخت ناموفق، رکورد duplicate، timeout API. تفاوت کد حرفهای در این است که خطا قابل پیشبینی، قابل log و قابل نمایش امن به کاربر باشد.
Throwable — Exception و Error
PHP 7+ هر دو implements Throwable. Error برای engine (TypeError، ParseError) — معمولاً catch نمیکنید. Exception برای business و application.
try {
$order = $service->place($data);
} catch (PaymentFailedException $e) {
return back()->withErrors(['payment' => $e->getMessage()]);
} catch (Throwable $e) {
report($e);
throw $e;
}
Exception سفارشی domain
class OrderNotFoundException extends Exception
{
public function __construct(public readonly int $orderId)
{
parent::__construct("Order {$orderId} not found");
}
}
catch مشخص — نه Exception generic برای همه.
چه زمانی throw؟
- وضعیت غیرقابل ادامه — نه expected flow
- caller نمیتواند recover کند
- برای validation ورودی — Form Request نه exception
Laravel Exception Handler
bootstrap/app.php یا App\Exceptions\Handler (نسخههای قدیم):
->withExceptions(function (Exceptions $exceptions) {
$exceptions->reportable(function (PaymentFailedException $e) {
// custom log context
});
$exceptions->render(function (OrderNotFoundException $e, Request $request) {
if ($request->expectsJson()) {
return response()->json(['message' => $e->getMessage()], 404);
}
});
})
report vs render
report— Sentry، log، Slackrender— پاسخ HTTP به کاربر
finally و transaction
DB::transaction(function () {
// auto rollback on exception
});
Transaction — ترجیح بر try-finally دستی.
نمایش خطا production
APP_DEBUG=false — stack trace به کاربر نه. پیام عمومی + id در log.
logging context
Log::error('Payment failed', [
'order_id' => $order->id,
'gateway' => 'zarinpal',
'code' => $e->getCode(),
]);
تست exception
expect(fn () => $action->handle($badData))
->toThrow(OrderNotFoundException::class);
anti-patterns
- catch خالی
- exception برای control flow عادی
- پیام خطا با SQL یا path
- @ suppression operator
جمعبندی
Exception domain-specific + handler مرکزی. PSR: PSR-3 log. Clean: Clean Code.