ERROR হ্যান্ডলিং এবং এক্সেপশন (The Safety Net)
সফটওয়্যার ক্র্যাশ করবেই—এটা বাস্তবতা। কিন্তু ক্র্যাশ করার পর ইউজার কী দেখবে এবং ডেভেলপার কীভাবে নোটিফিকেশন পাবে— সেটাই একজন সিনিয়রের ডিজাইনের বিষয়।
এই অধ্যায়ে আমরা পিএইচপির এরর হ্যান্ডলিং সিস্টেমের পোস্টমর্টেম করব।
৮.১ try-catch-finally এর ইন্টারনাল বিহেভিয়ার
পিএইচপিতে এক্সেপশন হলো একটি Class-based মেকানিজম, আর এরর হলো Event-based সিগন্যাল।
🔄 স্ট্যাক আনওয়াইন্ডিং (Stack Unwinding)
যখন একটি এক্সেপশন throw করা হয়, তখন পিএইচপি কারেন্ট ফাংশন এক্সিকিউশন বন্ধ করে দেয়। এরপর সে Call Stack ধরে পেছনের দিকে যেতে থাকে (Rewind) যতক্ষণ না সে একটি ম্যাচিং catch ব্লক পায়। একে বলা হয় Stack Unwinding।
✨ finally ব্লকের জাদুকরী ক্ষমতা
অনেকে জানেন না যে try ব্লকের ভেতর যদি return থাকে, তবুও finally ব্লক এক্সিকিউট হবেই।
function test() {
try {
echo "Try... ";
return "Return Value"; // ফাংশন এখান থেকেই শেষ হওয়ার কথা
} finally {
echo "Finally!";
}
}
echo test();
// Output: Try... Finally! Return Value
📌 Senior Use Case: ডাটাবেস কানেকশন ক্লোজ করা বা ফাইল হ্যান্ডেল রিলিজ করার জন্য finally সেরা জায়গা।
৮.২ কাস্টম এক্সেপশন ক্লাস (Professional Architecture)
জেনারেট Exception ক্লাস ব্যবহার করা জুনিয়রদের লক্ষণ। সিনিয়রা ডোমেইন স্পেসিফিক এক্সেপশন তৈরি করে।
❌ Bad
throw new Exception("User ID invalid");
✅ Senior Level (PHP 8 Constructor Promotion)
class ValidationException extends Exception {
public function __construct(
string $message,
public array $errors = [], // কাস্টম ডেটা
int $code = 422
) {
parent::__construct($message, $code);
}
}
// Usage
throw new ValidationException("Invalid Input", ['email' => 'Required']);
💡 লাভ: আপনি catch (ValidationException $e) দিয়ে স্পেসিফিক এরর ধরতে পারেন এবং এরর ফিল্ডগুলো রেসপন্সে পাঠাতে পারেন।
৮.৩ এক্সেপশন চেইনিং (The Root Cause Analysis)
ধরা যাক, আপনার ডাটাবেস কানেকশন ফেইল করেছে। আপনি ইউজারকে বললেন "Service Unavailable", কিন্তু লগ ফাইলে আসল কারণ (SQL Error) রাখতে চান। এটাই Exception Chaining।
try {
$db->connect();
} catch (PDOException $e) {
// আগের এক্সেপশন ($e) কে ৩য় প্যারামিটারে পাস করা হলো
throw new DatabaseConnectionException("System Error", 500, $e);
}
- 🔒 Security: ইউজার টেকনিক্যাল এরর দেখবে না
- 🐛 Debugging: লগ ফাইলে চেইন ধরে আসল কারণ (PDOException) দেখা যাবে
৮.৪ এরর হ্যান্ডলার ওভাররাইড (Error to Exception)
পিএইচপির পুরনো Notice, Warning গুলো try-catch দিয়ে ধরা যায় না। এগুলোকে এক্সেপশনে কনভার্ট করে নেওয়াই আধুনিক প্র্যাকটিস।
set_error_handler(function ($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) {
return; // সাইলেন্সড এরর (@) ইগনোর করা
}
// ওয়ার্নিংকেও এক্সেপশন বানিয়ে ফেলা হলো
throw new ErrorException($message, 0, $severity, $file, $line);
});
এখন undefined index বা file not found এর মতো ওয়ার্নিংগুলোও catch ব্লকে ধরা পড়বে।
৮.৫ লগিং সিস্টেম (Monolog) - The Standard
echo বা die দিয়ে ডিবাগ করা পাপ। পিএইচপির স্ট্যান্ডার্ড লগিং লাইব্রেরি হলো Monolog (লারাভেল/সিম্ফনি ডিফল্টভাবে এটি ব্যবহার করে)।
🏗️ আর্কিটেকচার:
Monolog এর কনসেপ্ট হলো Handlers। আপনি একই লগ একই সাথে ফাইলে, স্ল্যাকে এবং ইমেইলে পাঠাতে পারেন।
use MonologLogger;
use MonologHandlerStreamHandler;
use MonologHandlerSlackWebhookHandler;
$log = new Logger('App');
$log->pushHandler(new StreamHandler('app.log', Logger::WARNING));
$log->pushHandler(new SlackWebhookHandler($webhookUrl, Logger::CRITICAL));
// এটা শুধু ফাইলে যাবে
$log->warning("Disk space low");
// এটা ফাইল + স্ল্যাক দুই জায়গাতেই যাবে
$log->critical("Database Down!");
৮.৬ Fatal Error বনাম Exception (PHP 7+ Evolution)
পিএইচপি ৭-এর আগে Fatal Error হলে স্ক্রিপ্ট সাথে সাথে মরে যেত, ধরা যেত না। পিএইচপি ৭+ এ আর্কিটেকচার বদলে গেছে।
📐 The Throwable Hierarchy
এখন সব এরর এবং এক্সেপশন Throwable ইন্টারফেস ইমপ্লিমেন্ট করে।
Throwable
├── Exception (লজিক্যাল এরর, যেমন: UserNotFound)
└── Error (ইঞ্জিন এরর, যেমন: TypeError, ParseError)
💻 কোড উদাহরণ:
try {
undefinedFunction(); // এটা আগে ক্র্যাশ করত
} catch (Error $e) { // এখন এটা ধরা যাবে
echo "Caught Fatal Error: " . $e->getMessage();
}
💡 Senior Rule: গ্লোবাল হ্যান্ডলারে সবসময় catch (Throwable $e) ব্যবহার করুন, শুধু Exception নয়।
৮.৭ শাটডাউন ফাংশন (Crash Recovery)
কিছু এরর এখনো catch করা যায় না (যেমন: Memory Exhausted বা Time Limit Exceeded)। এদের ধরার জন্য শেষ ভরসা হলো register_shutdown_function।
register_shutdown_function(function () {
$error = error_get_last();
// যদি টাইপ E_ERROR বা E_PARSE হয়
if ($error && ($error['type'] === E_ERROR)) {
// সাইট ক্র্যাশ করেছে, এডমিনকে মেইল পাঠাও বা লগ করো
file_put_contents('crash_report.log', json_encode($error));
echo "Sorry, severe system error occurred.";
}
});
এটি স্ক্রিপ্ট শেষ হওয়ার ঠিক আগ মুহূর্তে রান করে।
৮.৮ এন্টারপ্রাইজ এরর হ্যান্ডলিং আর্কিটেকচার
একটি মডার্ন অ্যাপ্লিকেশনের এরর ফ্লো কেমন হওয়া উচিত?
- Entry Point:
index.phpতে গ্লোবাল try-catch থাকে - Service Layer: স্পেসিফিক CustomException থ্রো করে
- Global Handler: Throwable ক্যাচ করে, লগিং করে (Monolog)
- Environment Check:
- Local: স্ট্যাক ট্রেসসহ এরর দেখায়
- Production: সুন্দর JSON মেসেজ ("Something went wrong") এবং 500 স্ট্যাটাস কোড দেয়
📝 Pseudo Code for Production Handler
try {
$app->run();
} catch (Throwable $e) {
$logger->error($e); // ১. লগ করো
if ($env === 'production') {
http_response_code(500);
echo json_encode(["error" => "Internal Server Error"]); // ২. ক্লিন রেসপন্স
} else {
dd($e); // ৩. ডেভ মোডে ডিটেইলস
}
}
🎯 Senior Developer Interview Questions (Chapter 8)
Q: Exception এবং Error এর মধ্যে পার্থক্য কী? পিএইচপি ৭-এ কী পরিবর্তন এসেছে?
Exception সাধারণত অ্যাপ্লিকেশনের লজিক্যাল ভুল, আর Error হলো পিএইচপি ইঞ্জিনের ইন্টারনাল ভুল (যেমন টাইপ মিসম্যাচ)। পিএইচপি ৭-এ দুটোই Throwable ইন্টারফেসের আন্ডারে এসেছে, তাই এখন ইঞ্জিন এররও catch করা যায়।
Q: একটি try ব্লকে return স্টেটমেন্ট থাকলে finally ব্লক কি রান করবে?
হ্যাঁ, ফাংশন রিটার্ন করার ঠিক আগ মুহূর্তে finally ব্লক এক্সিকিউট হবে।
Q: Exception Chaining কেন ব্যবহার করা হয়?
অরিজিনাল এরর (যেমন Database Query Failed) লুকিয়ে ইউজারকে একটি জেনেরিক এরর দেওয়ার সময়, ডিবাগিংয়ের সুবিধার্থে অরিজিনাল এররটি নতুন এক্সেপশনের সাথে লিঙ্ক করে রাখার জন্য চেইনিং ব্যবহার করা হয়।
Q: set_error_handler কেন ব্যবহার করবেন?
পিএইচপির লিগ্যাসি এররগুলো (Notice, Warning) কে মডার্ন Exception এ কনভার্ট করার জন্য, যাতে সেগুলো try-catch ব্লকে হ্যান্ডেল করা যায়।
🎯 অধ্যায় ৮ এর সারাংশ (Summary)
এই অধ্যায়ে আমরা শিখলাম:
- ✓Stack Unwinding: Exception throw হলে Call Stack পেছানে যায় catch খোঁজার জন্য
- ✓finally: return থাকলেও এক্সিকিউট হয় - resource cleanup এর জন্য best
- ✓Custom Exceptions: Domain-specific exceptions with custom data
- ✓Exception Chaining: Root cause analysis এর জন্য previous exception পাস করা
- ✓set_error_handler: পুরনো Notice/Warning কে Exception এ কনভার্ট করা
- ✓Throwable: PHP 7+ - Exception এবং Error উভয়ই catch করা যায়
- ✓Monolog: PSR-3 standard logging with multiple handlers
✨ এখন আপনি জানেন কীভাবে একটি সিস্টেমকে ক্র্যাশ থেকে বাঁচাতে হয় বা ক্র্যাশ করলেও কীভাবে তার পোস্টমর্টেম করতে হয়।
পরবর্তী অধ্যায়: Part 9 — PHP Security (The Fortress) — যেখানে SQL Injection, XSS Prevention এবং Security Headers নিয়ে আলোচনা হবে।
প্রস্তুত তো? 🚀