Monday, August 31, 2009

PHP GD: allow PHP to decide image type

It is at times quite troublesome having the need to detect what image type is the file, then decide which function (imagecreatefromjpeg, imagecreatefrompng or imagecreatefromgif) to use for the image. Well, here's a simple solution.

<?php

$src = "http://example.com/image.jpg";
$image = imagecreatefile($src);

function imagecreatefile($f){
$content = file_get_contents($f);
return imagecreatefromstring($content);
}

?>


That's a great and easy way. However, the bad thing is that there will be an overhead of a function and a large variable $content. Having the variable $content in the function scope allows the variable to be disposed at the end of the function, saving memory.

To fix the large variable, you can do this instead:
<?php

$src = "http://example.com/image.jpg";
$image = imagecreatefile($src);

function imagecreatefile($f){
return imagecreatefromstring(file_get_contents($f));
}

?>


Hope it helps!

Thursday, August 27, 2009

PHP new development site/manual

I was browsing the web earlier on, and I chanced upon one of the PHP website development server at http://pb11.php.net/

Some comments:
the interface (UI) is definitely much better and everything's clearer.
however, the layout and contents are much about the same from the current one.

So you can try it out at http://pb11.php.net/

Take note that the mirror is unofficial and is not updated to the latest.

Monday, August 24, 2009

Optimize your code: Keep functions out of statements!

It's always said that we should think out of the box. In any programming language, we should write functions out of certain statements statements.

Consider this:
<?php

$arr = array(/* 10000 elements */);
for($i = 0; $i < count($arr); $i++){
// ...
}

?>


If you work this out slowly using a debugger or what, you would have noticed that count($arr) will be called for each iteration of the for loop! Each time you call count($arr), count() actually works out your array size and if your array is huge, the script will be stuck at this loop for a few seconds.

So what about doing something like this?
<?php

$arr = array(/* 10000 elements */);
$l = count($arr);
for($i = 0; $i < $l; $i++){
// ...
}

?>

Isn't this logically cleaner and faster in execution?

This also applies to while loop.

PHP Arrays - End vs Indices

I've looked through the PHP Arrays function list lately while working on some php scripts that requires lots of interaction with Arrays. It came to me that the following 2 are the identical:

$value = end($array);
$value2 = $array[count($array)-1];

But which is more efficient?

In a test, I tested both with a 1000 elements array. A total of 5 tests were ran and an average of 0.00040926s for using end() and 0.00041699s for using $arr[count($arr)-1].

That was only a single dimension array. Which means that all the elements are non-arrays. The moment i ran on a 2 dimensional array, the test results differ! Again I ran 5 tests, and an average of 0.00070285s for using end() and 0.00040769s for $arr[count($arr)-1].

Why? end() has to move the internal pointer of the array all the way to the end of the array. However, end() is still useful for arrays whose keys are not numeric.

The codes for the test can be found on pastebin at http://thephpcode.pastebin.com/f7fa7d00c

Friday, August 14, 2009

MySQL transaction (rollback+commit) - better with PHP

Lately I've been working on a project that has MySQL tables with relationship to each other. I have several functions that accesses the Database, and one function to call all these functions. However, I need to know that if one of the function that accesses the database fails, I need to do a rollback.

Here's how we can do it:

<?php
function addShop($shop){

$ok = true;
$ok = $ok && mysql_query('START TRANSACTION');

$ok = $ok && shops_AddShop($shop);
$ok = $ok && ($shop['id'] = mysql_insert_id());
$ok = $ok && shops_UpdateCategories($shop);

if($ok){
mysql_query('COMMIT');
}else{
mysql_query('ROLLBACK');
}

return $ok;
}

?>


If one of the MySQL queries failed, I can do a rollback and reverse the appropriate changes. It's much better taking advantage of the short circuit evaluation as talked about earlier on.

In that case you will have a more stable application.

Getting function name in a function

I came to this time when I was doing recursive functions. I thought that if I change the function name, I will have to change the name again in the codes within the function. Consider the function below.

<?php

function a($v){
$ret = array();
if(is_array($v))
{
foreach($v as $k){
$ret[] = a($k);
}
}else{
$ret = $v;
}
return $ret;
}

?>


If i were to change the function name, and I forgot to change the one within the code, I will cause myself an error and debug intensively.

However using backtrace, I am able to get the function name when inside a function. The function below enables you to get the function name when called.

<?php

function func_name(){
$bt = debug_backtrace();
$ret = '';
if(isset($bt[1]) && isset($bt[1]['function'])){
$ret = $bt[1]['function'];
}
return $ret;
}

?>


So to get the first function working even after changing function name:

<?php

function a($v){
$ret = array();
if(is_array($v))
{
$f = func_name();
foreach($v as $k){
$ret[] = $f($k);
}
}else{
$ret = $v;
}
return $ret;
}

?>


And there you have it!

This function was extracted from the php class (/class/php.class.php) of the fast and lightweight PHP framework - Samstyle PHP Framework 1.2.9 Alpha

Sunday, August 9, 2009

Happy Birthday Singapore!

We, the citizens of Singapore, pledge ourselves as one united people, regardless of race, language or religion, to build a democratic society, based on justice and equality, so as to achieve happiness, prosperity and progress for our nation.

Happy Birthday Singapore!

Friday, August 7, 2009

Calculating Age using Birthday in PHP

Here's some food for the thoughts: calculating age using birthday in PHP.

<?php

function getAge($birthday){
$dt = strtotime($birthday);
// convert the birthday to a standard format (UNIX epoch)
$a = gmdate('Y') - gmdate('Y',$dt);
// find the difference of years
return $a; // return the age.
}

?>


And here we have, a simple Age calculating function which is useful when displaying age on User profiles or calculating age restriction and so on.

For example, you can put this against a movie age rating checker:
<?php

$bday = '1993-04-05';
$age = getAge($bday);

$movies = getPGMovies();

if($age >= 21){
// R21 and below can be watched
$movies= array_merge($movies,getR21Movies());
}
if($age >= 18){
// M18 and below can be watched
$movies= array_merge($movies,getM18Movies());
}
if($age >= 16){
// NC16 and below can be watched
$movies= array_merge($movies,getNC16Movies());
}
// display $movies
?>

Wednesday, August 5, 2009

Improving and Speed up Conditional Expressions

This is something cool and you can implement in your PHP scripts, and also you should make this a habit for most of your programming languages - and that is Short Circuit Evaluation.

Consider the following code:

<?php

function a(){
echo 'a';
return true;
}

function b(){
echo 'b';
return false;
}

if(b() && a()){
echo 'c';
}

?>


When run, the output is only 'b'. Reason being that when the if statement is run, the checks from bracket then left to right. If the first expression evaluates into false, the second will not be run.

Now take a look at the OR comparison operator.

<?php

function a(){
echo 'a';
return false;
}

function b(){
echo 'b';
return true;
}

if(b() || a()){
echo 'c';
}

?>


This time, the output is 'bc'. Reason being that the expression in IF will be evaluated to the first true. if the first true is found, the rest will not be executed.

This allows you to speed up your application. Think about the following code:

<?php

$url = htmlentities($_POST['url']);

if($url == '' || validate::url($url)){
echo 'URL is not valid.';
}else{
echo 'Valid URL provided';
}

?>


It'll help to save time if the string is empty - since Short Circuit Evaluation parses that $url is empty, so it's a true and it won't bother to execute the rest of the expression.