Wednesday, March 11, 2015

Yii2: How to Handle Fatal Error.

Fatal error happen when your program process over the php memory limit, or longer process time. It will cause your program to abort or stop the existing process. Without proper handle this issue, the page might look unprofessional.

Here is the tutorial:

Step 1. Prepare file (lib/error.handler.php) with the following code:

function fatalErrorHandler()
{
  // Where yii_log function located
  require_once( __DIR__.DIRECTORY_SEPARATOR.'backend.lib.php'); 
  
  //to get last error message
  $error = error_get_last(); 

  // To track fatal run-time errors
  If ($error['type'] == E_ERROR){

    // to log error note and send email alert.
    yii_log($error, 'error'); 

    // temporary key for jquery to validate 
    echo '<div style="display:none" id="fatal-error">true</div>'; 
     }
   }

  register_shutdown_function('fatalErrorHandler');

Step 2. Include the following code in (config/web.php and config/console.php)

include_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'../lib/error.handler.php');

Step 3. Prepare file (lib/backend.lib.php) with the following code:

function yii_log($message, $level, $exit = FALSE) {
  $message = is_array($message) ? $message['message'] : $message;
  $message = date('Y-m-d H:i:s', time()). ' ' . substr((string)microtime(), 1, 8) . ' - ' . $message;
  switch (strtolower($level)) {
    case 'error':
      Yii::error($message);
      break;
    case 'warning':
      Yii::warning($message);
      break;      
    case 'info':
      Yii::info($message);
      break;
    case 'trace':
    default:
      Yii::trace($message);
      break;
  }
  // Yii::log($message, $level);
  Yii::getLogger()->flush();

  // also alert via email
  send_email_alert($message);
  if($exit) {
    exit();
  }
}

function send_email_alert($message) {
  $from = get_no_reply_email();
  $sendTo = get_alert_email();
  $app_name = Yii::$app->name;

  $headers="From: {$from}\r\nReply-To: {$from}";
  mail($sendTo, $app_name . ' Alert', $message, $headers);

}

Step 4. Prepare Ajax file (check_error.js) checking

$(document).ready(function() {
if ($("#fatal-error").length) {
    //$("upload-csv-form").before('
File: '+decodeURIComponent(getCookie('csvfile')).match(/"(.+)"/)[1]+' import was failed!
'); var filename = decodeURIComponent(getCookie('csvfile')).match(/"(.+)"/)[1]; var postData = { csvfile: filename}; if (typeof yii.getCsrfToken != 'undefined' && yii.getCsrfToken() != '' ) { postData[yii.getCsrfParam()] = yii.getCsrfToken(); } $.ajax({ url: '/member/updatestatus', data: postData, type: 'POST', dataType: 'jason', success: function(){ } }); $("pre").replaceWith('
Importing of '+filename+' did not complete successfully because of a server side error (no memory, performance issues or connection issues).
'); } });
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1);
        if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
    }

Step 5. Register js file in view file
$this->registerJsFile($this->getAssetManager()->getPublishedUrl('@app/themes/dashboard').'/js/check_error.js', ['position' => $this::POS_END]);

No comments:

Post a Comment