Kodokon kodokon.com

अपवाद: पदानुक्रम, finally, वैश्विक हैंडलर

एक संपूर्ण त्रुटि रणनीति बनाएँ: शृंखलाबद्ध व्यावसायिक अपवाद, नियंत्रित finally और रक्षा की अंतिम पंक्ति के रूप में वैश्विक हैंडलर।

9 मिनट · 3 प्रश्न

इस पाठ को Kodokon में खोलें

PHP 7 से, जो कुछ भी फेंका जाता है वह Throwable को कार्यान्वित करता है, जिसकी दो शाखाएँ हैं: Error (इंजन और टाइपिंग की विफलताएँ, जैसे TypeError) और Exception (एप्लिकेशन की विफलताएँ)। आप Error को केवल प्रोग्राम की सीमाओं पर पकड़ते हैं। एप्लिकेशन की तरफ, SPL एक बना-बनाया पदानुक्रम देता है: LogicException किसी डेवलपर बग का संकेत देता है, जिसे ठीक करना है; RuntimeException किसी रनटाइम आकस्मिकता का, जिसे संभालना है। पेशेवर सहज-बोध: अपने व्यावसायिक अपवादों को इन आधारों से व्युत्पन्न करें, हर पहचान योग्य स्थिति के लिए एक।

PHP
<?php

declare(strict_types=1);

abstract class AppException extends RuntimeException
{
}

final class UserNotFound extends AppException
{
    public static function withEmail(
        string $email
    ): self {
        return new self("No user for $email");
    }
}

try {
    throw UserNotFound::withEmail('lea@example.com');
} catch (UserNotFound $e) {
    echo $e->getMessage();
}
व्यावसायिक पदानुक्रम: आप स्तर के अनुसार UserNotFound, AppException या RuntimeException पकड़ते हैं।

try/catch तभी सार्थक है जब आपको पता हो कि त्रुटि का क्या करना है - वरना, इसे ऊपर बुलबुले की तरह उठने दें। तीन औज़ार नियंत्रण को परिष्कृत करते हैं: मल्टी-कैच catch (JsonException | ValueError $e) एक समान हैंडलिंग को समूहित करता है; previous पैरामीटर मूल कारण को शृंखलाबद्ध करता है जब आप किसी तकनीकी अपवाद को व्यावसायिक अपवाद में अनूदित करते हैं; और finally हर स्थिति में चलता है - सफलता, अपवाद, यहाँ तक कि जल्दी return होने पर भी - किसी संसाधन को मुक्त करने के लिए आदर्श।

PHP
<?php

declare(strict_types=1);

final class PayloadInvalid extends RuntimeException
{
}

function decode(string $json): mixed
{
    try {
        return json_decode(
            $json,
            true,
            flags: JSON_THROW_ON_ERROR,
        );
    } catch (JsonException $e) {
        throw new PayloadInvalid(
            'Invalid JSON payload',
            previous: $e,
        );
    } finally {
        echo "decode() finished\n";
    }
}

try {
    decode('{broken');
} catch (PayloadInvalid $e) {
    echo $e->getPrevious()?->getMessage();
}
अपवाद अनुवाद: तकनीकी कारण getPrevious() के ज़रिए सुलभ बना रहता है।

शृंखला के अंत में, दो वैश्विक हैंडलर व्यवस्था को पूरा करते हैं। set_exception_handler उस सब कुछ को पकड़ता है जो संभाला नहीं गया था: संरचित लॉगिंग, एक सामान्य 500 प्रतिक्रिया - बिना कभी उपयोगकर्ता को संदेश या ट्रेस उजागर किए। set_error_handler पुरानी त्रुटियों (warnings, notices) को ErrorException में बदल देता है, दोनों दुनियाओं को एकीकृत करते हुए: सब कुछ एक अपवाद बन जाता है, सब कुछ एक ही हैंडलिंग पथ का अनुसरण करता है।

PHP
<?php

declare(strict_types=1);

set_error_handler(function (
    int $severity,
    string $message,
    string $file,
    int $line,
): bool {
    throw new ErrorException(
        $message,
        0,
        $severity,
        $file,
        $line,
    );
});

set_exception_handler(function (Throwable $e): void {
    error_log($e->getMessage());
    http_response_code(500);
    echo 'A technical error occurred.';
});

trigger_error('Legacy warning', E_USER_WARNING);
echo 'Never reached';
warning एक अपवाद बन जाती है, बिना पकड़ी गई: वैश्विक हैंडलर प्रतिक्रिया देता है, फिर स्क्रिप्ट रुक जाती है।

ज्ञान जांच

सुनिश्चित करें कि आपको इस पाठ के मुख्य बिंदु याद हैं।

  1. आधुनिक PHP में Error और Exception में क्या समानता है?
    • Error, Exception से वंशानुक्रम पाता है
    • दोनों Throwable इंटरफ़ेस को कार्यान्वित करते हैं
    • दोनों PHP इंजन के लिए आरक्षित हैं
  2. finally ब्लॉक कब चलता है?
    • केवल तभी जब कोई अपवाद न फेंका गया हो
    • केवल किसी catch के बाद
    • हर स्थिति में: सफलता, अपवाद पकड़ा गया हो या नहीं, जल्दी return
  3. किसी अपवाद का previous पैरामीटर किसलिए है?
    • जब आप किसी अपवाद को उच्च-स्तरीय अपवाद में अनूदित करते हैं तब मूल अपवाद को संरक्षित करना
    • अपवाद को कॉल स्टैक में ऊपर उठने से रोकना
    • अगली विफलता पर फेंके जाने वाले अपवाद को परिभाषित करना