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]);

Thursday, December 18, 2014

Yii: Check Column Exists before Create Column with Migration Script

You need only 3 simple step to Create Column via Migration Script.

Step 1:
- Create Migration Script with yiic command:
- Goto project and run the following command


protected/yiic migrate create alter_table_column


Step 2:
- Go to folder path protected/migrations and look for file name mxxxxxx_xxxxx_alter_table_column.php
- Add the following command in function up.


public function up()
 {
  $table = Yii::app()->db->schema->getTable('table_name');
  if(!isset($table->columns['column_name'])) {
      // Column doesn't exist then create column
   $this->addColumn('table_name', 'column_name', 'int(11) NOT NULL');
  }
 }

Step 3:
- Run migration script with the following command:


protected/yiic migrate 


~ EOF. Thanks for Reading. ~

Monday, November 10, 2014

PHP Packing Solution - How to divide items equally

This tutorial concept is actually come from stackoverflow where the solution was suggested in ruby script but I had translate it in PHP script.

$list_of_bags = array(11, 41, 31, 15, 15, 66, 67, 34, 20, 42, 22, 25);
# total weight of all bags
$weight_of_bags = array_sum($list_of_bags);
# how many containers do we have at our disposal?
$number_of_containers = 4;
# How much should one container weight?
$weight_per_container = $weight_of_bags / $number_of_containers;
# We make an array containing an empty array for each container
$containers[] = array();

$total = 0;

# For each bag
foreach ($list_of_bags as $bag) {
    for($i=0; $i<$number_of_containers; $i++){

        $total = (isset($containers[$i])) ? array_sum($containers[$i]) : 0;
        if($total + $bag < $weight_per_container){
            $containers[$i][] = $bag;
            break;
        }
    }
}

# output all containers with the number of items and total weight
foreach ($containers as $index=>$container) {
   echo "container $index has ";
   echo count($container);
   echo " ";
   echo "items and weigths: ";
   echo array_sum($container);
   echo "
";
}
Output:
container 0 has 3 items and weigths: 83
container 1 has 3 items and weigths: 96
container 2 has 2 items and weigths: 87
container 3 has 2 items and weigths: 76
container 4 has 2 items and weigths: 47

Wednesday, November 5, 2014

PHP Recursive Function

Tutorial by: Adam Lim


For example we need to create calculation as below:
5 => (5*2)+(4*2)+(3*2)+(2*1)+(1*1)

It can be resolved by for loop as below:

$total=0;
for($i=5; $i=0; $i--){
  $total += $i * 2;
}


To create a recursive function, it should as follow:

function test($int){
  if($int>0){
    echo $int.<br>;
    return(($int*2) + test($int-1));     // call back self function to continue loop
  }else{
    return 0;
  }
}

echo test(5);

Output:
5
4
3
2
1
30

DEMO

Dynamic Photo Framing API

Today bonus is to introduce photo framing api(apisilo.com) for framing industry. It is easy to use as you just need to pass four parameters which is art, frametop, framebtm, and framesize.

Parameter values and file format:
art - Photo or the artwork you wish to frame (only jpg, gif, png file format)
frametop - small piece of frame image, please see sample. (only jpg, gif, png file format)
framebtm - small piece of frame image, please see sample. (only jpg, gif, png file format)
framesize - integer value that you wish to control frame thickness.

How to use it:

Use with jquery getJSON to call API

$.getJSON("http://frame.apisilo.com/index.php?jsoncallback=?",
    {
      art: "http://www.tourismeoutaouais.com/blogue/wp-content/uploads/2014/10/halloween2-620x350.jpg",
      frametop: "http://www.imagemagick.org/Usage/thumbnails/blackthin_btm.gif",
      framebtm: "http://www.imagemagick.org/Usage/thumbnails/blackthin_btm.gif",
      framesize:"50"
    },
    function(data) {
        var str = data['result'];
        var finalData = str.replace(/\\/gi, '');

        $("#framed_artwork").attr("src",finalData);
    });

Append the result in framed_artwork as following:
<img id="framed_artwork" src="sample.jpg" />


DEMO

Monday, October 27, 2014

Step By Step Cross Domain Pass Parameter

Objective of this tutorial is helping those who want to create api but having the issue of cross domain problem.

How to Create Client Call API
Step 1:
Create javascript file name myjsfile.js and paste the following codes.

$(function(){
  $('#btn_name').on('click', function(e){
    $.getJSON("http://www.yourotherdomain.com/myapifile.php?jsoncallback=?",
    {
      variable1: "maybe textbox value",
      variable2: "maybe textbox value",
      variable3: "maybe textbox value"
    },
    function(data) {
        var str = data['result'];
        alert(str);
    });
  });
});

Step 2:
Include the following code before </head> tag.

<script src="js/myjsfile.js" type="text/javascript"></script>

You are now able to pass parameter to function from difference domain http://www.yourotherdomain.com/myapifile.php  .


How to Create Server Response
Step 1:
Create php file name myapifile.php and paste the following codes.

<?php
 header("Content-Type: application/json, charset: utf-8;");
 $arr=array();
 $arr['result'] = "Here is your result data";
 echo $_GET['jsoncallback'].'('.json_encode($arr).');';
 exit;
?>

~End~

Notice:
You may get Uncaught SyntaxError: Unexpected token if you did not include $_GET['jsoncallback'].

References:
http://stackoverflow.com/questions/3143698/uncaught-syntaxerror-unexpected-token
http://www.w3resource.com/JSON/JSONP.php