আমি কীভাবে কোনও পিএইচপি মারাত্মক (`E_ERROR`) ত্রুটি ধরতে পারি?


557

আমি set_error_handler()বেশিরভাগ পিএইচপি ত্রুটিগুলি ধরতে ব্যবহার করতে পারি , তবে এটি মারাত্মক ( E_ERROR) ত্রুটির জন্য কাজ করে না , যেমন কোনও ফাংশন কল করে যা অস্তিত্বহীন। এই ত্রুটিগুলি ধরার অন্য কোনও উপায় আছে কি?

আমি ফোন করার চেষ্টা করছি mail() সমস্ত ত্রুটিগুলির জন্য এবং পিএইচপি 5.2.3 চালাচ্ছি।


আমি পিএইচপি-তে সমস্ত ত্রুটি ধরার সম্পূর্ণ সমাধান সহ একটি উইকি-স্টাইলের প্রশ্নোত্তর লিখেছিলাম; যা স্ট্যাক ওভারফ্লোতে এখানে দেখতে / শিথিল / চুরি / সমালোচনা করা যেতে পারে । সমাধানের মধ্যে পাঁচটি পদ্ধতি রয়েছে যা সমস্ত ত্রুটি মোড়ানো পিএইচপি উত্পাদন করতে পারে যা শেষ পর্যন্ত 'ত্রুটিহ্যান্ডলার' টাইপযুক্ত অবজেক্ট পর্যন্ত ত্রুটিগুলি পাস করবে।
ডিজিটালজেদি 805



উত্তর:


635

এটি ব্যবহার করে মারাত্মক ত্রুটিগুলি লগ করুন register_shutdown_function, যার জন্য পিএইচপি 5.2+ প্রয়োজন:

register_shutdown_function( "fatal_handler" );

function fatal_handler() {
    $errfile = "unknown file";
    $errstr  = "shutdown";
    $errno   = E_CORE_ERROR;
    $errline = 0;

    $error = error_get_last();

    if($error !== NULL) {
        $errno   = $error["type"];
        $errfile = $error["file"];
        $errline = $error["line"];
        $errstr  = $error["message"];

        error_mail(format_error( $errno, $errstr, $errfile, $errline));
    }
}

আপনি সংজ্ঞায়িত করতে হবে error_mailএবং format_errorফাংশন। উদাহরণ স্বরূপ:

function format_error( $errno, $errstr, $errfile, $errline ) {
    $trace = print_r( debug_backtrace( false ), true );

    $content = "
    <table>
        <thead><th>Item</th><th>Description</th></thead>
        <tbody>
            <tr>
                <th>Error</th>
                <td><pre>$errstr</pre></td>
            </tr>
            <tr>
                <th>Errno</th>
                <td><pre>$errno</pre></td>
            </tr>
            <tr>
                <th>File</th>
                <td>$errfile</td>
            </tr>
            <tr>
                <th>Line</th>
                <td>$errline</td>
            </tr>
            <tr>
                <th>Trace</th>
                <td><pre>$trace</pre></td>
            </tr>
        </tbody>
    </table>";
    return $content;
}

ব্যবহারের সুইফট মেলার লিখতে error_mailফাংশন।

আরো দেখুন:


113
+1 এটি আসল সঠিক উত্তর। আমি জানি না কেন লোকেরা "আপনি মারাত্মক ত্রুটিগুলি থেকে পুনরুদ্ধার করতে পারবেন না" - কেন এই প্রশ্নটি পুনরুদ্ধার সম্পর্কে কিছু বলেনি।
ডেভিড হার্কনেস

21
ধন্যবাদ, ভাল। মারাত্মক ত্রুটিগুলি থেকে পুনরুদ্ধার (উদাহরণস্বরূপ মেমরির সীমা) এমন কিছু নয় যা আমি করার চেষ্টা করব তবে এই ত্রুটিগুলি আবিষ্কারযোগ্য (গ্রাহক কোনও সমর্থন টিকিট জমা না দিয়ে) তৈরি করা সমস্ত পার্থক্য তৈরি করে।
ইলিজা

2
প্রাথমিক মেল ব্যবহার করে:mail("myname@myemail.com", "My Site: FATAL ERROR", "Details: " . $errno . ' ' . $errstr . ' ' . $errfile . ' ' . $errline);
এরিক মুয়সার

4
@ স্কটনিকোল স্লাভা ভি সঠিক, কারণ স্ক্রিপ্টটি চলমান শেষের সময় শাটডাউন ফাংশনটি ডাকা হয়। কোডটি এখন যেভাবে লেখা হয়েছে তা দিয়ে, প্রতিটি পৃষ্ঠা লোডে একটি ইমেল প্রেরণ করা হবে।
Nate

2
দ্রষ্টব্য: এটি একটি 100% সঠিক উত্তর নয়। ত্রুটি উপেক্ষা করার জন্য @ প্রতীক ব্যবহার করা যে কোনও জায়গা এখনও শেষ ত্রুটিটি সেট করবে (যাতে আপনি ত্রুটিগুলি পরিচালনা করতে পারেন)। সুতরাং আপনার স্ক্রিপ্টটি সমস্যা ছাড়াই শেষ হয়েছে তবে রেজিস্টার_শটাউন_ফংশনটি এখনও মনে করে একটি ত্রুটি ঘটেছে। কেবলমাত্র পিএইচপি 7 এর পরে যদিও তাদের একটি ক্রিয়াকলাপ ছিল_ক্রিয়ার_লাস্ট ()।
রাহলি

150

আমি সবেমাত্র এই সমাধানটি নিয়ে এসেছি (পিএইচপি 5.2.0+):

function shutDownFunction() {
    $error = error_get_last();
     // Fatal error, E_ERROR === 1
    if ($error['type'] === E_ERROR) {
         // Do your stuff
    }
}
register_shutdown_function('shutDownFunction');

পূর্বনির্ধারিত ধ্রুবকগুলিতে বিভিন্ন ত্রুটির ধরণের সংজ্ঞা দেওয়া হয় ।


25
শীর্ষস্থানীয় উত্তরের চেয়ে এই সমাধানটি আমার পক্ষে আরও অনেক কিছু করে। শীর্ষস্থানীয় উত্তরটি কোনও ত্রুটি না থাকলেও প্রতিবার স্ক্রিপ্ট চলার সময় আপনাকে একটি ইমেল প্রেরণ করবে। এটি কঠোরভাবে মারাত্মক ত্রুটিতে চলে runs
kmoney12

@ স্পিকারলিস, যদি শেষ ত্রুটিটি ইতিমধ্যে পরিচালনা করা হয়ে থাকে তবে ত্রুটি_সামগ্রী_কালেও কি এটি ফিরিয়ে দেবে না?
পেসারিয়ার

@ পেসারিয়ার আমি নিশ্চিত যে আপনি "হ্যান্ডলড" এর অর্থ কী, ত্রুটিগুলি ব্যতিক্রম নয়, তবে আমি মনে করি উত্তরটি "হ্যাঁ"
পেরিক্লিস

3
@ পেসার আমি দেখছি, এটি একটি আকর্ষণীয় প্রশ্ন। Php.net/error_get_lastএকবার দেখুন , একটি মন্তব্যে উল্লেখ করা হয়েছে যে " If an error handler (see set_error_handler ) successfully handles an error then that error will not be reported by this function."
পেরিক্লিস

1
সম্ভবত এটি সুস্পষ্ট, কলিং register_shutdown_function()অবশ্যই মারাত্মক ত্রুটির চেয়ে বেশি আগে হওয়া উচিত। use_1T_memory(); /* memory exhausted error here! */ register_shutdown_function('shutDownFunction');প্রত্যাশার মতো কাজ করবে না
নুবু

117

মারাত্মক ত্রুটিগুলি ধরা এবং পুনরুদ্ধারের জন্য পিএইচপি প্রচলিত উপায় সরবরাহ করে না। এটি কারণ মারাত্মক ত্রুটির পরে প্রক্রিয়াজাতকরণ পুনরুদ্ধার করা উচিত নয়। স্ট্রিং একটি আউটপুট বাফারের সাথে মেলে (যেমন পিএইচপি নেটনে বর্ণিত কৌশলটি মূল পোস্টটি দ্বারা পরামর্শ দেওয়া হয়েছে) অবশ্যই অসুস্থ-পরামর্শযুক্ত। এটি কেবল অবিশ্বাস্য।

ত্রুটি হ্যান্ডলার পদ্ধতির মধ্যে থেকে মেল () ফাংশনটি কল করাও সমস্যাযুক্ত বলে প্রমাণিত। আপনার যদি অনেক ত্রুটি ঘটে থাকে তবে আপনার মেল সার্ভারটি কাজের সাথে বোঝা হয়ে উঠবে এবং আপনি নিজেকে জাঁকজমকপূর্ণ ইনবক্সের সাহায্যে খুঁজে পেতে পারেন। এটি এড়াতে, আপনি পর্যায়ক্রমে ত্রুটি লগগুলি স্ক্যান করতে ক্রোন চালানো বিবেচনা করতে পারেন এবং সে অনুযায়ী বিজ্ঞপ্তি প্রেরণ করতে পারেন। আপনি নাগিওসের মতো সিস্টেম মনিটরিং সফটওয়্যারটিও দেখতে পছন্দ করতে পারেন ।


শাটডাউন ফাংশনটি নিবন্ধকরণ সম্পর্কে কিছুটা কথা বলতে:

এটি সত্য যে আপনি একটি শাটডাউন ফাংশনটি নিবন্ধভুক্ত করতে পারেন, এবং এটি একটি ভাল উত্তর।

এখানে মূল কথাটি হ'ল আমাদের সাধারণত মারাত্মক ত্রুটিগুলি থেকে পুনরুদ্ধার করার চেষ্টা করা উচিত নয়, বিশেষত আপনার আউটপুট বাফারের বিরুদ্ধে নিয়মিত অভিব্যক্তি ব্যবহার করে নয়। আমি গৃহীত উত্তরে সাড়া দিচ্ছিলাম জানছিলাম, যা পিএইচপিএন-র একটি পরামর্শের সাথে যুক্ত ছিল যা এরপরে পরিবর্তন বা সরানো হয়েছে।

এই পরামর্শটি ছিল ব্যতিক্রম হ্যান্ডলিংয়ের সময় আউটপুট বাফারের বিরুদ্ধে একটি রেজেক্স ব্যবহার করা, এবং মারাত্মক ত্রুটির ক্ষেত্রে (আপনি যে কনফিগার করা ত্রুটিযুক্ত পাঠ্যের প্রত্যাশা করছেন তার বিরুদ্ধে ম্যাচটি সনাক্ত করে) কিছুটা পুনরুদ্ধার বা অব্যাহত প্রক্রিয়াজাতকরণ করার চেষ্টা করুন। এটি একটি প্রস্তাবিত অনুশীলন হবে না (আমি বিশ্বাস করি যে কারণে আমিও মূল পরামর্শটি খুঁজে পাই না I'm আমি হয় এটি উপেক্ষা করছি, বা পিএইচপি সম্প্রদায় এটি নষ্ট করে দিয়েছে)।

এটি লক্ষণীয় বিষয় হতে পারে যে পিএইচপি এর আরও সাম্প্রতিক সংস্করণগুলি (প্রায় 5.1) আউটপুট বাফারিং কলব্যাকের আগে vক্যবদ্ধ হওয়ার আগে শটডাউন ফাংশনটি কল করেছিল। সংস্করণ 5 এবং তার আগের সংস্করণে, সেই আদেশটি ছিল বিপরীত (আউটপুট বাফারিং কলব্যাকটি শটডাউন ফাংশনটির পরে হয়েছিল)। এছাড়াও, প্রায় 5.0.5 (যা প্রশ্নকারীর সংস্করণ 5.2.3 এর তুলনায় অনেক আগে), নিবন্ধিত শাটডাউন ফাংশন বলার আগে অবজেক্টগুলি ভালভাবে লোড করা হয়, সুতরাং আপনি আপনার মেমোরি অবজেক্টগুলিতে নির্ভর করতে পারবেন না অনেক কিছুই।

সুতরাং শাটডাউন ফাংশনটি নিবন্ধন করা ঠিক আছে, তবে শাটডাউন ফাংশনটি সম্পাদন করা উচিত এমন কিছু কাজ সম্ভবত মুষ্টিমেয় কোমল শাটডাউন পদ্ধতিতে সীমাবদ্ধ।

এখানে কী গ্রহণযোগ্য তা হ'ল যে কেউ এই প্রশ্নের জন্য হোঁচট খায় এবং মূলত গৃহীত উত্তরের পরামর্শটি দেখে তার পক্ষে জ্ঞানের কিছু শব্দ। আপনার আউটপুট বাফারকে পুনরায় সংযুক্ত করবেন না।


25
পিএফএফ, আমি সেই 650.000+ ই-মেলগুলি পরের দিন সকালে পেয়েছি মনে আছে। তার পর থেকে আমার ত্রুটিহ্যান্ডলারটি প্রতি ওয়েবসভারে 100 টি ইমেলের প্রতিচ্ছবিযুক্ত।
বব ফ্যাঙ্গার

14
এটা সত্যি না. আপনি রেজিস্টার_শুটডাউন_ফংশন দিয়ে মারাত্মক ত্রুটিগুলি ক্যাপচার করতে পারেন।
হিপারট্র্যাকার

56
মারাত্মক ত্রুটিগুলি ধরার জন্য সেখানে ব্যবহারের কেস রয়েছে। উদাহরণস্বরূপ, পরীক্ষার স্যুটগুলি যখন কেউ ব্যর্থ হয় কেবল তখনই থামানো উচিত নয়, তাদের মারাত্মক ত্রুটির খবর দেওয়া উচিত এবং পরবর্তী পরীক্ষায় যাওয়া উচিত। পিএইচপি কেবলমাত্র অনেক কিছুই "মারাত্মক" ত্রুটি করে makes
চাদ

24
হ্যাঁ তারা "ধরা উচিত নয়" বলা খুব সংক্ষিপ্ত দৃষ্টিতে। একটি উৎপাদন ব্যবস্থা, আপনি প্রয়োজন যখন জানতে কিছু ব্যর্থ হয় (- ডিফল্ট পিএইচপি ত্রুটি পরিচালনা খুব বাস্তবধর্মী নয় ইমেল সেট আপ করতে বা একটি ডাটাবেসের মধ্যে জিনিষ লগ ইন করুন)।
বিটি

8
"আপনারা কীভাবে ত্রুটিগুলি ধরা দরকার, যাতে আমরা সেগুলি ঠিক করতে পারি" - আপনি কী বলছেন সে সম্পর্কে একটি তাত্পর্যপূর্ণ মন্তব্য করতে চাই ...
কেলি এলটন

37

ঠিক আছে, মারাত্মক ত্রুটি অন্য কোনওভাবে ধরা সম্ভব বলে মনে হচ্ছে :)

ob_start('fatal_error_handler');

function fatal_error_handler($buffer){
    $error = error_get_last();
    if($error['type'] == 1){
        // Type, message, file, line
        $newBuffer='<html><header><title>Fatal Error </title></header>
                      <style>
                    .error_content{
                        background: ghostwhite;
                        vertical-align: middle;
                        margin:0 auto;
                        padding: 10px;
                        width: 50%;
                     }
                     .error_content label{color: red;font-family: Georgia;font-size: 16pt;font-style: italic;}
                     .error_content ul li{ background: none repeat scroll 0 0 FloralWhite;
                                border: 1px solid AliceBlue;
                                display: block;
                                font-family: monospace;
                                padding: 2%;
                                text-align: left;
                      }
                      </style>
                      <body style="text-align: center;">
                        <div class="error_content">
                             <label >Fatal Error </label>
                             <ul>
                               <li><b>Line</b> ' . $error['line'] . '</li>
                               <li><b>Message</b> ' . $error['message'] . '</li>
                               <li><b>File</b> ' . $error['file'] . '</li>
                             </ul>

                             <a href="javascript:history.back()"> Back </a>
                        </div>
                      </body></html>';

        return $newBuffer;
    }
    return $buffer;
}

3
আমি যদি এটি করতে পারি তবে এই 10 টি উপাখোজি দেবো। এটি আমার পক্ষে সেই অদ্ভুত ত্রুটিগুলির জন্য নিখুঁতভাবে কাজ করে যা কখনও কখনও ঘটে যখন কোনও পৃষ্ঠা বোমা এবং কোনও কিছুই লগইন করা হয় না। আমি লাইভ প্রোডাকশন কোডে ব্যবহার করব না তবে যখন ব্যর্থ হচ্ছে তার একটি দ্রুত উত্তর প্রয়োজন হলে কোনও পৃষ্ঠাতে যুক্ত করা ভাল। ধন্যবাদ!
নাইট আউল

ইন্টারনেটে আমি খুঁজে পেয়েছি সেরা সমাধানগুলির মধ্যে একটি। মোহন মত কাজ করে।
11:53

কোন পথে? একটি ব্যাখ্যা ক্রমযুক্ত হবে, বিশেষত এটি যদি ইন্টারনেটের অন্যতম সেরা সমাধান হয় (এটি আরও উন্নত হতে পারে)।
পিটার মর্টেনসেন

যেমন, সমস্ত সিএসএস সামগ্রী প্রয়োজন? এটি প্রয়োজনীয় কাটা যাবে না? আপনার উত্তর সম্পাদনা করে প্রতিক্রিয়া জানান, এখানে মন্তব্যে নয় (যথাযথ হিসাবে)।
পিটার মর্টেনসেন

@ পিটারমোরটেনসেন আমি এর সেরা দাবি করি না। সমস্যাটির এটির আমার ব্যক্তিগত সমাধানও রয়েছে, আরও অনেক ভাল বিকল্প রয়েছে আরও পেশাদার। কারও দ্বারা প্রস্তাবিত এটি উত্পাদন জন্য উপযুক্ত নয়। CSS আছে সেখানে আমি স্রেফ আমার ব্যক্তিগত কোডটি কাট-পেস্ট করেছি
সখুনজাই

36

মারাত্মক ত্রুটি বা আদায়যোগ্য মারাত্মক ত্রুটি এখন দৃষ্টান্ত নিক্ষেপ Errorমধ্যে পিএইচপি 7 বা উচ্চতর সংস্করণগুলি । অন্য যে কোনও ব্যতিক্রমের মতো, অবরুদ্ধ Errorব্যবহার করে অবজেক্টগুলি ধরা যেতে পারে try/catch

উদাহরণ:

<?php
$variable = 'not an object';

try {
    $variable->method(); // Throws an Error object in PHP 7 or higger.
} catch (Error $e) {
    // Handle error
    echo $e->getMessage(); // Call to a member function method() on string
}

https://3v4l.org/67vbk

বা আপনি Throwableসমস্ত ব্যতিক্রম ধরা ইন্টারফেস ব্যবহার করতে পারেন ।

উদাহরণ:

<?php
    try {
        undefinedFunctionCall();
    } catch (Throwable $e) {
        // Handle error
        echo $e->getMessage(); // Call to undefined function undefinedFunctionCall()
    }

https://3v4l.org/Br0MG

আরও তথ্যের জন্য: http://php.net/manual/en/language.erferences.php7.php


2
কোনও আইডিয়া কীভাবে এটি ব্যবহার করার মতো ত্রুটি ধরতে Fatal error: Trait 'FailedTrait' not found inব্যবহার করবেন ReflectionClass?
টিসিবি 13

1
@ TCB13 একটি ফাইলে চেষ্টা ভেতরের বিষয়বস্তু মোড়ানো চেষ্টা include "filename.php"পরিবর্তে tryব্লক, তারপর Throwableজন্য অন্তত কাজ এ ব্লক ধরা ParseError
নিলোকট

24

আমি পিএইচপি (প্রায় সমস্ত) এ ত্রুটিযুক্ত সমস্ত ধরণের ধরার জন্য একটি উপায় তৈরি করেছি! E_CORE_ERROR সম্পর্কে আমার কোনও নিশ্চিত নেই (আমি মনে করি কেবল সেই ত্রুটির জন্য কাজ করবে না)! তবে, অন্যান্য মারাত্মক ত্রুটির জন্য (E_ERROR, E_PARSE, E_COMPILE ...) কেবলমাত্র একটি ত্রুটি হ্যান্ডলার ফাংশন ব্যবহার করে সূক্ষ্ম কাজ করে! আমার সমাধান আছে:

আপনার মূল ফাইলটিতে এই কোডটি রাখুন (index.php):

<?php
    define('E_FATAL',  E_ERROR | E_USER_ERROR | E_PARSE | E_CORE_ERROR |
            E_COMPILE_ERROR | E_RECOVERABLE_ERROR);

    define('ENV', 'dev');

    // Custom error handling vars
    define('DISPLAY_ERRORS', TRUE);
    define('ERROR_REPORTING', E_ALL | E_STRICT);
    define('LOG_ERRORS', TRUE);

    register_shutdown_function('shut');

    set_error_handler('handler');

    // Function to catch no user error handler function errors...
    function shut(){

        $error = error_get_last();

        if($error && ($error['type'] & E_FATAL)){
            handler($error['type'], $error['message'], $error['file'], $error['line']);
        }

    }

    function handler( $errno, $errstr, $errfile, $errline ) {

        switch ($errno){

            case E_ERROR: // 1 //
                $typestr = 'E_ERROR'; break;
            case E_WARNING: // 2 //
                $typestr = 'E_WARNING'; break;
            case E_PARSE: // 4 //
                $typestr = 'E_PARSE'; break;
            case E_NOTICE: // 8 //
                $typestr = 'E_NOTICE'; break;
            case E_CORE_ERROR: // 16 //
                $typestr = 'E_CORE_ERROR'; break;
            case E_CORE_WARNING: // 32 //
                $typestr = 'E_CORE_WARNING'; break;
            case E_COMPILE_ERROR: // 64 //
                $typestr = 'E_COMPILE_ERROR'; break;
            case E_CORE_WARNING: // 128 //
                $typestr = 'E_COMPILE_WARNING'; break;
            case E_USER_ERROR: // 256 //
                $typestr = 'E_USER_ERROR'; break;
            case E_USER_WARNING: // 512 //
                $typestr = 'E_USER_WARNING'; break;
            case E_USER_NOTICE: // 1024 //
                $typestr = 'E_USER_NOTICE'; break;
            case E_STRICT: // 2048 //
                $typestr = 'E_STRICT'; break;
            case E_RECOVERABLE_ERROR: // 4096 //
                $typestr = 'E_RECOVERABLE_ERROR'; break;
            case E_DEPRECATED: // 8192 //
                $typestr = 'E_DEPRECATED'; break;
            case E_USER_DEPRECATED: // 16384 //
                $typestr = 'E_USER_DEPRECATED'; break;
        }

        $message =
            '<b>' . $typestr .
            ': </b>' . $errstr .
            ' in <b>' . $errfile .
            '</b> on line <b>' . $errline .
            '</b><br/>';

        if(($errno & E_FATAL) && ENV === 'production'){

            header('Location: 500.html');
            header('Status: 500 Internal Server Error');

        }

        if(!($errno & ERROR_REPORTING))
            return;

        if(DISPLAY_ERRORS)
            printf('%s', $message);

        //Logging error on php file error log...
        if(LOG_ERRORS)
            error_log(strip_tags($message), 0);
    }

    ob_start();

    @include 'content.php';

    ob_end_flush();
?>

2
'কন্টেন্ট.এফপি' যুক্ত লাইনটি কী করে?
মার্কো

22

আপনি মারাত্মক ত্রুটিগুলি ধরতে / পরিচালনা করতে পারবেন না, তবে আপনি তাদের লগ / রিপোর্ট করতে পারেন। দ্রুত ডিবাগিংয়ের জন্য আমি এই সাধারণ কোডটির একটি উত্তর পরিবর্তন করেছি

function __fatalHandler()
{
    $error = error_get_last();

    // Check if it's a core/fatal error, otherwise it's a normal shutdown
    if ($error !== NULL && in_array($error['type'],
        array(E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING,
              E_COMPILE_ERROR, E_COMPILE_WARNING,E_RECOVERABLE_ERROR))) {

        echo "<pre>fatal error:\n";
        print_r($error);
        echo "</pre>";
        die;
    }
}

register_shutdown_function('__fatalHandler');

তবে এই কোডটি কোথায় যাবে?
TKoL

@TKoL প্রথম লাইন। মূলত আপনার স্ক্রিপ্ট / প্রোগ্রামের ফাইল এন্ট্রি করুন, সুতরাং এটি প্রথমে কার্যকর করে, যদি এটি সম্ভব না হয় তবে এটি একটি সাধারণ ফাইলে রাখে
zainengineer

17

আপনি নিবন্ধিত শাটডাউন ফাংশনটির মতো একটি ব্যতিক্রম ছুঁড়ে ফেলতে পারবেন না:

<?php
    function shutdown() {
        if (($error = error_get_last())) {
           ob_clean();
           throw new Exception("fatal error");
        }
    }

    try {
        $x = null;
        $x->method()
    } catch(Exception $e) {
        # This won't work
    }
?>

তবে আপনি ক্যাপচার এবং অনুরোধটি অন্য পৃষ্ঠায় পুনর্নির্দেশ করতে পারেন।

<?php
    function shutdown() {
        if (($error = error_get_last())) {
           ob_clean();
           # Report the event, send email, etc.
           header("Location: http://localhost/error-capture");
           # From /error-capture. You can use another
           # redirect, to e.g. the home page
        }
    }
    register_shutdown_function('shutdown');

    $x = null;
    $x->method()
?>

11

আপনি যদি পিএইচপি> = 5.1.0 ব্যবহার করছেন তবে ত্রুটি-অনুগ্রহ শ্রেণীর সাহায্যে এই জাতীয় কিছু করুন:

<?php
    // Define an error handler
    function exception_error_handler($errno, $errstr, $errfile, $errline ) {
        throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
    }

    // Set your error handler
    set_error_handler("exception_error_handler");

    /* Trigger exception */
    try
    {
        // Try to do something like finding the end of the internet
    }
    catch(ErrorException $e)
    {
        // Anything you want to do with $e
    }
?>

9

জেন্ডার ফ্রেমওয়ার্ক 2 এ দুর্দান্ত সমাধান পাওয়া গেছে:

/**
 * ErrorHandler that can be used to catch internal PHP errors
 * and convert to an ErrorException instance.
 */
abstract class ErrorHandler
{
    /**
     * Active stack
     *
     * @var array
     */
    protected static $stack = array();

    /**
     * Check if this error handler is active
     *
     * @return bool
     */
    public static function started()
    {
        return (bool) static::getNestedLevel();
    }

    /**
     * Get the current nested level
     *
     * @return int
     */
    public static function getNestedLevel()
    {
        return count(static::$stack);
    }

    /**
     * Starting the error handler
     *
     * @param int $errorLevel
     */
    public static function start($errorLevel = \E_WARNING)
    {
        if (!static::$stack) {
            set_error_handler(array(get_called_class(), 'addError'), $errorLevel);
        }

        static::$stack[] = null;
    }

    /**
     * Stopping the error handler
     *
     * @param  bool $throw Throw the ErrorException if any
     * @return null|ErrorException
     * @throws ErrorException If an error has been catched and $throw is true
     */
    public static function stop($throw = false)
    {
        $errorException = null;

        if (static::$stack) {
            $errorException = array_pop(static::$stack);

            if (!static::$stack) {
                restore_error_handler();
            }

            if ($errorException && $throw) {
                throw $errorException;
            }
        }

        return $errorException;
    }

    /**
     * Stop all active handler
     *
     * @return void
     */
    public static function clean()
    {
        if (static::$stack) {
            restore_error_handler();
        }

        static::$stack = array();
    }

    /**
     * Add an error to the stack
     *
     * @param int    $errno
     * @param string $errstr
     * @param string $errfile
     * @param int    $errline
     * @return void
     */
    public static function addError($errno, $errstr = '', $errfile = '', $errline = 0)
    {
        $stack = & static::$stack[count(static::$stack) - 1];
        $stack = new ErrorException($errstr, 0, $errno, $errfile, $errline, $stack);
    }
}

ErrorHandlerআপনার প্রয়োজন হলে এই ক্লাসটি আপনাকে নির্দিষ্ট শুরু করার অনুমতি দেয় । এবং তারপরে আপনি হ্যান্ডলারটিও বন্ধ করতে পারেন।

এই ক্লাস যেমন উদাহরণস্বরূপ ব্যবহার করুন:

ErrorHandler::start(E_WARNING);
$return = call_function_raises_E_WARNING();

if ($innerException = ErrorHandler::stop()) {
    throw new Exception('Special Exception Text', 0, $innerException);
}

// or
ErrorHandler::stop(true); // directly throws an Exception;

পূর্ণ শ্রেণীর কোডের লিঙ্ক:
https://github.com/zendframework/zf2/blob/master/library/Zend/Stdlib/ErrorHandler.php


একটি সম্ভবত আরও ভাল সমাধান যে এক থেকে মনোোলোগ এটির হ'ল :

পূর্ণ শ্রেণীর কোডের লিঙ্ক:
https://github.com/Seldaek/monolog/blob/master/src/Monolog/ErrorHandler.php

এটি register_shutdown_functionফাংশনটি ব্যবহার করে FATAL_ERRORS পরিচালনা করতে পারে । এই শ্রেণি অনুসারে একটি FATAL_ERROR নিম্নলিখিতগুলির মধ্যে একটি array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR)

class ErrorHandler
{
    // [...]

    public function registerExceptionHandler($level = null, $callPrevious = true)
    {
        $prev = set_exception_handler(array($this, 'handleException'));
        $this->uncaughtExceptionLevel = $level;
        if ($callPrevious && $prev) {
            $this->previousExceptionHandler = $prev;
        }
    }

    public function registerErrorHandler(array $levelMap = array(), $callPrevious = true, $errorTypes = -1)
    {
        $prev = set_error_handler(array($this, 'handleError'), $errorTypes);
        $this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap);
        if ($callPrevious) {
            $this->previousErrorHandler = $prev ?: true;
        }
    }

    public function registerFatalHandler($level = null, $reservedMemorySize = 20)
    {
        register_shutdown_function(array($this, 'handleFatalError'));

        $this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize);
        $this->fatalLevel = $level;
    }

    // [...]
}

9

পরিবর্তে স্থিতিশীল স্টাইলযুক্ত 503 পরিষেবা অনুপলব্ধ এইচটিএমএল আউটপুট দেখানোর জন্য আমাকে উত্পাদনের জন্য মারাত্মক ত্রুটিগুলি পরিচালনা করতে হবে । এটি অবশ্যই "মারাত্মক ত্রুটিগুলি ধরা" এর একটি যুক্তিসঙ্গত পন্থা। আমি এই কাজটি করেছি:

আমার একটি কাস্টম ত্রুটি হ্যান্ডলিং ফাংশন রয়েছে "ত্রুটি_হান্ডারকারী" যা কোনও "E_ERROR, E_USER_ERROR ইত্যাদিতে আমার" 503 পরিষেবা অনুপলব্ধ "এইচটিএমএল পৃষ্ঠা প্রদর্শন করবে এটি এখন আমার মারাত্মক ত্রুটি ধরায় শাটডাউন ফাংশনটিতে ডাকা হবে,

function fatal_error_handler() {

    if (@is_array($e = @error_get_last())) {
        $code = isset($e['type']) ? $e['type'] : 0;
        $msg = isset($e['message']) ? $e['message'] : '';
        $file = isset($e['file']) ? $e['file'] : '';
        $line = isset($e['line']) ? $e['line'] : '';
        if ($code>0)
            error_handler($code, $msg, $file, $line);
    }
}
set_error_handler("error_handler");
register_shutdown_function('fatal_error_handler');

আমার কাস্টম ত্রুটি_হ্যান্ডলার ফাংশনে, ত্রুটি যদি E_ERROR, E_USER_ERROR, ইত্যাদি হয় তবে আমিও কল করি @ob_end_clean(); বাফার খালি করতে, এইভাবে পিএইচপি এর "মারাত্মক ত্রুটি" বার্তা সরানোর।

কঠোর ইসসেট () চেকিং এবং এর গুরুত্বপূর্ণ নোটটি নিন @আমরা আমাদের ত্রুটি_হ্যান্ডলার স্ক্রিপ্টগুলিতে কোনও ত্রুটি উত্পন্ন করতে চাই না বলে সিলিং ফাংশনগুলির ।

এখনও কেপারোর সাথে একমত হয়ে মারাত্মক ত্রুটি ধরা "" তাত্ক্ষণিক ত্রুটি "এর উদ্দেশ্যকে পরাস্ত করে তাই আপনার আরও প্রক্রিয়াকরণ করার জন্য এটি সত্যিকার অর্থে নয়। এই শাটডাউন প্রক্রিয়াতে কোনও মেল () ফাংশন চালাবেন না কারণ আপনি অবশ্যই মেল সার্ভার বা আপনার ইনবক্সটি ব্যাকআপ করবেন। পরিবর্তে এই ঘটনাগুলি ফাইলগুলিতে লগ করুন এবং এই ত্রুটিযুক্ত.লগ ফাইলগুলি সন্ধান করতে ক্রোন জব শিডিউল করুন এবং প্রশাসকদের কাছে মেল করুন।


7

পিএইচপি-তে ক্যাচযোগ্য মারাত্মক ত্রুটি রয়েছে। এগুলি E_RECOVERABLE_ERROR হিসাবে সংজ্ঞায়িত করা হয়েছে। পিএইচপি ম্যানুয়াল একটি E_RECOVERABLE_ERROR এর বর্ণনা দেয়:

ধরাছোঁয় মারাত্মক ত্রুটি। এটি ইঙ্গিত দেয় যে সম্ভবত একটি বিপজ্জনক ত্রুটি ঘটেছে, তবে ইঞ্জিনটি অস্থির অবস্থায় ছাড়েনি। যদি ত্রুটিটি কোনও ব্যবহারকারীর সংজ্ঞায়িত হ্যান্ডেল দ্বারা ধরা না থাকে (দেখুন set_error_handler () দেখুন ), অ্যাপ্লিকেশনটি E_ERROR হিসাবে বাতিল হয়ে যায়।

আপনি set_error_handler () ব্যবহার করে এবং E_RECOVERABLE_ERROR পরীক্ষা করে এই "মারাত্মক" ত্রুটিগুলি " ধর " করতে পারেন । এই ত্রুটিটি ধরা পড়লে আমি একটি ব্যতিক্রম ছোঁড়াতে দরকারী বলে মনে করি, তারপরে আপনি চেষ্টা / ধরা ব্যবহার করতে পারেন।

এই প্রশ্নোত্তর একটি দরকারী উদাহরণ সরবরাহ করে: পিএইচপি টাইপ ইঙ্গিত করার জন্য আমি কীভাবে "ক্যাচবাল মারাত্মক ত্রুটি" ধরতে পারি?

E_ERROR ত্রুটিগুলি অবশ্য পরিচালনা করা যায়, তবে ইঞ্জিনটি অস্থির অবস্থায় থাকায় এটি পুনরুদ্ধার করা যায় না।


6

বর্তমান ত্রুটি_হেলার পদ্ধতি =) পাওয়ার জন্য এখানে একটি দুর্দান্ত কৌশল is

<?php
    register_shutdown_function('__fatalHandler');

    function __fatalHandler()
    {
        $error = error_get_last();

        // Check if it's a core/fatal error. Otherwise, it's a normal shutdown
        if($error !== NULL && $error['type'] === E_ERROR) {

            // It is a bit hackish, but the set_exception_handler
            // will return the old handler
            function fakeHandler() { }

            $handler = set_exception_handler('fakeHandler');
            restore_exception_handler();
            if($handler !== null) {
                call_user_func(
                    $handler,
                    new ErrorException(
                        $error['message'],
                        $error['type'],
                        0,
                        $error['file'],
                        $error['line']));
            }
            exit;
        }
    }
?>

এছাড়াও আমি নোট করতে চাই আপনি কল যদি

<?php
    ini_set('display_errors', false);
?>

পিএইচপি ত্রুটি প্রদর্শন বন্ধ করে দেয়। অন্যথায়, ত্রুটি পাঠ্য আপনার ত্রুটি হ্যান্ডলারের আগে ক্লায়েন্টকে প্রেরণ করা হবে।


1
Ini_set লাইনটির কারণে এটি উত্সাহিত হয়েছে ('প্রদর্শন_পদ্ধতি', মিথ্যা);
সাহেব খান

যদি কোনও কারণে এই বিটটি থাকে তবে এটি পিএইচপি ত্রুটিগুলি প্রদর্শন করবে এমনকি আপনি এটিকে
সাহেব খান

5

যেহেতু এখানে বেশিরভাগ উত্তর অপ্রয়োজনীয়ভাবে ভার্বোজ, তাই এখানে আমার শীর্ষে ভোট দেওয়া উত্তরের কুৎসিত সংস্করণ:

function errorHandler($errno, $errstr, $errfile = '', $errline = 0, $errcontext = array()) {
    //Do stuff: mail, log, etc
}

function fatalHandler() {
    $error = error_get_last();
    if($error) errorHandler($error["type"], $error["message"], $error["file"], $error["line"]);
}

set_error_handler("errorHandler")
register_shutdown_function("fatalHandler");

4

আসলে তা না. মারাত্মক ত্রুটিগুলি একে বলা হয়, কারণ এগুলি মারাত্মক। আপনি তাদের কাছ থেকে পুনরুদ্ধার করতে পারবেন না।


12
ধরা এবং পুনরুদ্ধার দুটি খুব আলাদা জিনিস।
সাইমন ফারসবার্গ

3

"স্যান্ডবক্স" কোডটিকে মারাত্মক ত্রুটির কারণ হতে পারে এটি সম্ভব করার জন্য আমি এই ফাংশনটি তৈরি করেছি। যেহেতু বন্ধ থেকে ফেলে দেওয়া ব্যতিক্রমগুলি register_shutdown_functionপ্রাক মারাত্মক ত্রুটি কল স্ট্যাক থেকে নির্গত হয় না, তাই এটি ব্যবহারের একটি অভিন্ন উপায় সরবরাহ করার জন্য আমি এই ফাংশনটির পরে প্রস্থান করতে বাধ্য হই।

function superTryCatchFinallyAndExit( Closure $try, Closure $catch = NULL, Closure $finally )
{
    $finished = FALSE;
    register_shutdown_function( function() use ( &$finished, $catch, $finally ) {
        if( ! $finished ) {
            $finished = TRUE;
            print "EXPLODE!".PHP_EOL;
            if( $catch ) {
                superTryCatchFinallyAndExit( function() use ( $catch ) {
                    $catch( new Exception( "Fatal Error!!!" ) );
                }, NULL, $finally );                
            } else {
                $finally();                
            }
        }
    } );
    try {
        $try();
    } catch( Exception $e ) {
        if( $catch ) {
            try {
                $catch( $e );
            } catch( Exception $e ) {}
        }
    }
    $finished = TRUE;
    $finally();
    exit();
}

3

এমন কিছু পরিস্থিতিতে রয়েছে যেখানে মারাত্মক ত্রুটিগুলিও ধরা উচিত (কৃপণভাবে বেরিয়ে আসার আগে আপনাকে কিছুটা সাফ করার প্রয়োজন হতে পারে এবং কেবল মারা যাবেন না)।

আমি আমার একটি pre_system হুক বাস্তবায়িত হয়েছে CodeIgniter যাতে আমি ইমেল মাধ্যমে আমার মারাত্মক ত্রুটি পেতে পারেন অ্যাপ্লিকেশন, এবং এই আমাকে বাগ যে রিপোর্ট করা হয় নি (অথবা পরে তারা স্থির ছিল রিপোর্ট করা হয়েছিল, আমি ইতিমধ্যেই তাদের সম্পর্কে জানত যেমন :)) খোঁজার সাহায্য করেছিল।

ত্রুটিটি ইতিমধ্যে রিপোর্ট করা হয়েছে কিনা তা সেন্ডমেল চেক করে যাতে এটি আপনাকে একাধিকবার জ্ঞাত ত্রুটিযুক্ত করে স্প্যাম না করে।

class PHPFatalError {

    public function setHandler() {
        register_shutdown_function('handleShutdown');
    }
}

function handleShutdown() {
    if (($error = error_get_last())) {
        ob_start();
        echo "<pre>";
        var_dump($error);
        echo "</pre>";
        $message = ob_get_clean();
        sendEmail($message);
        ob_start();
        echo '{"status":"error","message":"Internal application error!"}';
        ob_flush();
        exit();
    }
}

কি "Sendemail" ? আপনি কী সেন্দমেল ( এখানে আপনার মন্তব্যে নয়, উত্তরটি সম্পাদনা করে প্রতিক্রিয়া) বোঝাতে চান ?
পিটার মর্টেনসেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.