जब तक आप कुछ सार्थक करने का इरादा नहीं रखते तब तक आपको अपवाद को नहीं पकड़ना चाहिए ।
"कुछ सार्थक" इनमें से एक हो सकता है:
अपवाद को संभालना
सबसे स्पष्ट सार्थक कार्रवाई अपवाद को संभालने के लिए है, उदाहरण के लिए एक त्रुटि संदेश प्रदर्शित करने और ऑपरेशन को निरस्त करके:
try {
$connect = new CONNECT($db, $user, $password, $driver, $host);
}
catch (Exception $e) {
echo "Error while connecting to database!";
die;
}
लॉगिंग या आंशिक सफाई
कभी-कभी आप नहीं जानते कि किसी विशिष्ट संदर्भ के अंदर अपवाद को कैसे ठीक से संभालना है; शायद आपको "बड़ी तस्वीर" के बारे में जानकारी की कमी है, लेकिन आप विफलता को उस बिंदु के करीब से लॉग इन करना चाहते हैं जहां यह संभव हुआ। इस स्थिति में, आप पकड़ना, लॉग इन करना और फिर से फेंकना चाहते हैं:
try {
$connect = new CONNECT($db, $user, $password, $driver, $host);
}
catch (Exception $e) {
logException($e); // does something
throw $e;
}
एक संबंधित परिदृश्य वह है जहां आप असफल ऑपरेशन के लिए कुछ सफाई करने के लिए सही जगह पर हैं, लेकिन यह तय करने के लिए नहीं कि विफलता को शीर्ष स्तर पर कैसे नियंत्रित किया जाए। पहले के PHP संस्करणों में इसे लागू किया जाता था
$connect = new CONNECT($db, $user, $password, $driver, $host);
try {
$connect->insertSomeRecord();
}
catch (Exception $e) {
$connect->disconnect(); // we don't want to keep the connection open anymore
throw $e; // but we also don't know how to respond to the failure
}
PHP 5.5 ने finally
कीवर्ड की शुरुआत की है , इसलिए क्लीनअप परिदृश्यों के लिए अब इसे अप्रोच करने का एक और तरीका है। यदि क्लीन कोड को कोई फर्क नहीं पड़ता है कि क्या हुआ है (यानी त्रुटि पर और सफलता दोनों पर) तो अब ऐसा करना संभव है, जबकि पारदर्शी रूप से किसी भी अपवाद को फेंकने की अनुमति नहीं है:
$connect = new CONNECT($db, $user, $password, $driver, $host);
try {
$connect->insertSomeRecord();
}
finally {
$connect->disconnect(); // no matter what
}
अमूर्त त्रुटि (अपवाद जंजीर के साथ)
एक तीसरा मामला यह है कि आप तार्किक रूप से एक बड़ी छतरी के नीचे कई संभावित विफलताओं को समूह बनाना चाहते हैं। तार्किक समूहन के लिए एक उदाहरण:
class ComponentInitException extends Exception {
// public constructors etc as in Exception
}
class Component {
public function __construct() {
try {
$connect = new CONNECT($db, $user, $password, $driver, $host);
}
catch (Exception $e) {
throw new ComponentInitException($e->getMessage(), $e->getCode(), $e);
}
}
}
इस मामले में, आप उपयोगकर्ताओं को यह नहीं जानना चाहते Component
हैं कि यह डेटाबेस कनेक्शन का उपयोग करके कार्यान्वित किया गया है (हो सकता है कि आप अपने विकल्पों को खुला रखना चाहते हों और भविष्य में फ़ाइल-आधारित संग्रहण का उपयोग करें)। तो आपके विनिर्देशन Component
का कहना है कि "एक प्रारंभिक विफलता के मामले में, ComponentInitException
फेंक दिया जाएगा"। यह उपभोक्ताओं Component
को अपेक्षित प्रकार के अपवादों को पकड़ने की अनुमति देता है, जबकि डिबगिंग कोड को सभी (कार्यान्वयन-निर्भर) विवरण तक पहुंचने की अनुमति देता है ।
समृद्ध संदर्भ प्रदान करना (अपवाद की रूपरेखा के साथ)
अंत में, ऐसे मामले हैं जहां आप अपवाद के लिए अधिक संदर्भ प्रदान करना चाह सकते हैं। इस मामले में यह अपवाद को दूसरे में लपेटने के लिए समझ में आता है जो त्रुटि होने पर आप क्या करने की कोशिश कर रहे थे, इसके बारे में अधिक जानकारी रखते हैं। उदाहरण के लिए:
class FileOperation {
public static function copyFiles() {
try {
$copier = new FileCopier(); // the constructor may throw
// this may throw if the files do no not exist
$copier->ensureSourceFilesExist();
// this may throw if the directory cannot be created
$copier->createTargetDirectory();
// this may throw if copying a file fails
$copier->performCopy();
}
catch (Exception $e) {
throw new Exception("Could not perform copy operation.", 0, $e);
}
}
}
यह मामला उपरोक्त के समान है (और उदाहरण शायद सबसे अच्छा वाला नहीं आ सकता है), लेकिन यह अधिक संदर्भ प्रदान करने के बिंदु को दिखाता है: यदि कोई अपवाद फेंक दिया गया है, तो यह हमें बताता है कि फ़ाइल की प्रतिलिपि विफल हुई। लेकिन यह असफल क्यों हुआ? यह जानकारी लिपटे हुए अपवादों में प्रदान की गई है (जिनमें से एक से अधिक स्तर हो सकते हैं यदि उदाहरण अधिक जटिल था)।
ऐसा करने के मूल्य का सचित्र वर्णन किया गया है, यदि आप ऐसे परिदृश्य के बारे में सोचते हैं, जैसे कि UserProfile
ऑब्जेक्ट बनाते समय फ़ाइलों की प्रतिलिपि बनाई जाती है क्योंकि उपयोगकर्ता प्रोफ़ाइल फ़ाइलों में संग्रहीत होती है और यह लेनदेन शब्दार्थ का समर्थन करती है: आप परिवर्तनों को "पूर्ववत" कर सकते हैं क्योंकि वे केवल एक पर किए जाते हैं प्रोफ़ाइल की प्रतिलिपि जब तक आप नहीं करते।
इस मामले में, यदि आपने किया
try {
$profile = UserProfile::getInstance();
}
और इसके परिणामस्वरूप "लक्ष्य निर्देशिका नहीं बनाई जा सकी" अपवाद त्रुटि, आपको भ्रमित होने का अधिकार होगा। संदर्भ प्रदान करने वाले अन्य अपवादों की परतों में इस "कोर" अपवाद को लपेटने से त्रुटि से निपटने में बहुत आसान हो जाएगा ("प्रोफ़ाइल प्रतिलिपि बनाना विफल" -> "फ़ाइल कॉपी ऑपरेशन विफल" -> "लक्ष्य निर्देशिका नहीं बनाई जा सकती")।