Category: "PHP"

PHP - Catching session timeout issues

I've been working on a bug where an application is logging out unexpectedly.

To identify the piece of code that is destroying the session namespace I've been using the code snippet:

 ob_start();
 debug_print_backtrace();
 $trace = ob_get_contents();
 ob_end_clean(); 
 file_put_contents(basename(__FILE__).'.out', var_export($trace,true).PHP_EOL.var_export($_SERVER, ,true).PHP_EOL);

What it does is dumps out the stack that called the function it is placed in.

You can add additional information like a timestamp or FILE_APPEND.

You may also want to use Zend's logging. The reason I don't use it is that every instruction adds overhead. Once this issue is resolved, I'll remove all the debug code. I hope.

Credit to the link. :)

Linux Command Line - Convert XML to JSON

This was the answer to a question that came in an email - "Do you know of a good XML to JSON converter?"

Obviously you need php-cli, JSON, and SimpleXML. :)

The "xml" is the name of the file that contains the XML, the output can be piped to a different file.

php -r 'echo json_encode(simplexml_load_file("xml"));'

If you would like it pretty printed, this page is really nice: http://jsonprettyprint.com/

Upgrading PHP 5.3 to 5.4 - Checking your code (Linux)

If you are upgrading PHP from 5.3 to 5.4 for an existing application, you can use the following commands to check for parse errors.

tree -fi application | grep -E '.php|.phtml' | sed "s/^/php -l /" > files
source files > results

The output is really what comes out of stderr, which will be the parse errors.

Be sure to check out the short_open_tag directive (http://www.php.net/manual/en/ini.core.php#ini.short-open-tag).

By default <?= is enabled, to use <? for statements other than echo, you must enable the short_open_tag option in /etc/php.ini.

Create a PHP class from a database table

Simple script to get the columns from a database table and write out a PHP class.


$table = preg_replace('/\W/','',$argv[1]);
if (empty($table)) die ('Invalid table'.PHP_EOL);

try {
	$dbh = new PDO('mysql:host=localhost;dbname=test', 'root');

	$className = ucfirst($table);
	echo <<<START
<?php
Class Model_$className
	extends Model_Abstract {

START;

	$query = $dbh->query('DESCRIBE '.$argv[1]);
	$columns = $query->fetchAll(PDO::FETCH_CLASS);
	foreach ($columns as $row) {
		echo "\tprivate \${$row->Field};\n";
	}
echo '}';
} catch (PDOException $e) {
    print "Error!: " . $e->getMessage() . "
"; die(); } ?>

PHP - Sorting Objects - Performance Considerations

PHP has some great functions for sorting arrays, however, they should be used with care.

If you have an array of complex objects and plan to sort only on one value, you may see significant performance gains if you flatten the array into a single dimension and use the simpler library functions. The test run posted here shows a 10x improvement.

This is a very simple demonstration script that creates an array of 100 objects with a random value and timestamp. The array is sorted in ascending and descending order.

Sample output

Sorting an array of objects
------------------------------
uAsortBiDir ASC
Elapsed 0.001910924911499ms
uAsortUniDir ASC
Elapsed 0.0020918846130371ms
uAsortBiDir DESC
Elapsed 0.0018858909606934ms
uAsortUniDir DESC
Elapsed 0.0021059513092041ms

Sorting a flattened array
------------------------------
asort
Elapsed 0.00023484230041504ms
arsort (Reverse)
Elapsed 0.00020194053649902ms

<?php

// Arbitrary constants
define ('LIMIT',100);
define ('MIN', 0);
define ('MAX', 100);

// An array of objects 
$arr = array();
for ($i = 0; $i < LIMIT; $i++) {
	$arr[] = new Item(rand(MIN, MAX), microtime(true));
}

echo 'Sorting an array of objects'.PHP_EOL;
echo str_repeat('-',30).PHP_EOL;
$sorter = new Sorter;
echo 'uAsortBiDir ASC'.PHP_EOL;
$start = microtime(true);
uasort($arr, array($sorter, 'uAsortBiDir'));
$end= microtime(true);
echo 'Elapsed '.($end - $start).'ms'.PHP_EOL;

shuffle($arr);

echo 'uAsortUniDir ASC'.PHP_EOL;
$start = microtime(true);
uasort($arr, array($sorter, 'uAsortUniDir'));
$end= microtime(true);
echo 'Elapsed '.($end - $start).'ms'.PHP_EOL;

shuffle($arr);

$sorter = new Sorter(Sorter::DESC);
echo 'uAsortBiDir DESC'.PHP_EOL;
$start = microtime(true);
uasort($arr, array($sorter, 'uAsortBiDir'));
$end= microtime(true);
echo 'Elapsed '.($end - $start).'ms'.PHP_EOL;

shuffle($arr);

echo 'uAsortUniDir DESC'.PHP_EOL;
$start = microtime(true);
uasort($arr, array($sorter, 'uAsortUniDir'));
$arr = array_reverse($arr);
$end= microtime(true);
echo 'Elapsed '.($end - $start).'ms'.PHP_EOL;

shuffle($arr);

echo PHP_EOL;

echo 'Sorting a flattened array'.PHP_EOL;
echo str_repeat('-',30).PHP_EOL;
echo 'asort'.PHP_EOL;
$start = microtime(true);
$flat = array();
foreach ($arr as $index => $item) {
	$flat[$index] = $item->value;
}
asort($flat);
$new = array();
foreach ($flat as $index => $item) {
	$new[$index] = $arr[$index];
}
$end= microtime(true);
echo 'Elapsed '.($end - $start).'ms'.PHP_EOL;

shuffle($arr);

echo 'arsort (Reverse)'.PHP_EOL;
$start = microtime(true);
$flat = array();
foreach ($arr as $index => $item) {
	$flat[$index] = $item->value;
}
arsort($flat);
$new = array();
foreach ($flat as $index => $item) {
	$new[$index] = $arr[$index];
}
$end= microtime(true);
echo 'Elapsed '.($end - $start).'ms'.PHP_EOL;

Class Item {
	public $data = array();
	
	function __construct($value, $timestamp) {
		$this->data['value'] = $value;
		$this->data['timestamp'] = $timestamp;
	}

	function __get($property) {
		return $this->data[$property];
	}
}

Class Sorter {

	const ASC = 'asc';
	const DESC = 'desc';

	protected $dir;

	function __construct($dir = self::ASC) {
		$this->dir = $dir;
	}

	function uAsortBiDir($a, $b) {
		$cmp = ($a->value < $b->value);
		if ($this->dir === self::DESC) $cmp != $cmp;
		return $cmp;
	}

	function uAsortUniDir($a, $b) {
		$cmp = ($a->value < $b->value);
		return $cmp;
	}
}