Category: PHP

Information and howto articles for PHP

PHP is a powerful open source server-sided scripting language that can be used on a wide variety of operating systems and webservers, including Apache on UNIX and IIS on Windows.

PHP contains numerous extensions which enable you to dynamically create images and flash files, parse xml, connect to remote servers using pop, imap, ftp, http and raw sockets, natively access many database servers including PostgreSql, MySQL and Microsoft SQL Server, compress and decompress files, lookup domain names and and much more.

PHP has an excellent manual and online documentation which covers every function for every extension available.

MySQL connections and PHP forked processes

It is possible to fork a process with PHP and have one or more child processes running. If a connection has already been established to a MySQL database and the child processes run queries it’s quite likely a "MySQL server has gone away" or a "Lost connection to MySQL server during query" type error will occur.

Read More »

Testing if a PHP include file was included

PHP’s include() and include_once() functions can return values to the calling script which can be useful for testing to see if the file was actually included, for example if a configuration file whose filename is based on the website’s domain name was included. If no return value is set then it will return integer 1 if included, or boolean false if not.

Read More »

PHP script to export table creation SQL from MySQL

I was trying to export the structure of a MySQL database using phpMyAdmin but it kept timing out and not showing me the full create script. I think phpMyAdmin uses the information schema to get this information and its on a host with hundreds of databases and tables so querying the information schema runs very slowly. Instead I knocked together a quick PHP script to dump the structure instead and share it here.

Read More »

Prevent E_DEPRECATED error messages in PHP

PHP 5.3 introduced a new error reporting level E_DEPRECATED which is triggered when deprecated functions and methods are used, such as the old style ereg() regular expression functions. This post shows how to suppress E_DEPRECATED error messages.

Read More »

Autoloading with PHP’s SPL library

I read Rafael Dohms’s post “SPL: a hidden gem” a few days ago and learned of a better alternative to PHP’s __autoload function using SPL instead and thought I’d share this here along with some more details about the spl_autoload_register() and spl_autoload_functions() functions.

The useful thing about using spl_autoload_register over __autoload is that it allows the use of multiple autoloaders; __autoload can only have the single autoloading function.

Using a class

Rafael’s example looks like this:

class MyLoader{
 public static function doAutoload($class){
 // autoload process
 spl_autoload_register( array('MyLoader', 'doAutoload') );

Because an array is passed to the spl_autoload_register() function it knows to call MyLoader::doAutoload($class) when autoloading.

Using a function

It a string is passed instead of an array then it’s a function which is being called: therefore you can either make the autoloader a function or a class. A function example:

function MyFunctionLoader{
 // autoload process

If the autoloading function doesn’t exist

When I was testing this out I made the mistake of writing some code passing the function two parameters instead of an array and got the following error:

Fatal error: Uncaught exception 'LogicException' with message 'Function 'MyLoader' not found' in /common/examples/spl-load.php:9
 Stack trace:
 #0 /common/examples/spl-load.php(9): spl_autoload_register('MyLoader', true)
 #1 {main}
 thrown in /common/examples/spl-load.php on line 9

This is because if you pass a string as the first function it looks for a function and not a class. If you want a class to be used make sure you pass array(‘class’, ‘function’) and not ‘class’, ‘function’

Add __autoload()

When using spl_autoload_register the existing __autoload() function is not automatically added to the queue. You need to add it yourself. For example:

if(function_exists("__autoload")) {

Using multiple autoloaders

The following code will register all three of the above autoload functions:

if(function_exists("__autoload")) {
 spl_autoload_register(array('MyLoader', 'doAutoload'));

If a new class is created and doesn’t already exist in code, then the above functions will be called in the order they are registered and will stop as soon as the class is loaded. In the above example they’ll be called in this order:

  1. __autoload()
  2. MyLoader:doAutoLoad()
  3. MyFunctionLoader()

Showing which functions are registered

Use spl_autoload_functions() to get a list of functions that are registered.

$functions = spl_autoload_functions();

With the examples above registered, this will be the output from the array:

 [0] => __autoload
 [1] => Array
 [0] => MyLoader
 [1] => doAutoload
 [2] => my_loader
Read More »

Calculating a page’s bounce rate with the Google Analytics API

I had an email a couple of days ago from someone asking me how to calculate the bounce rate for a page using my PHP Class for the Google Analytics API.

The formula supplied from Google from the “Common Calculations” section of the Analytics API documentation says the bounce rate for a particular page should be caculated like this:


To work this out using my PHP Class you would do something like the following example. I’ve multiplied the caculation up by 100 to give a percentage in this example.

$data = $api->data($id, 'ga:pagePath', 'ga:bounces,ga:uniquePageviews');
 foreach($data as $page_path => $row) {
 $bounce_rate = round(100 * $row['ga:bounces'] / $row['ga:uniquePageviews'], 2);
 echo "$page_path $bounce_rate%n";

The round(…, 2) rounds the number to 2 decimal places (see my rounding numbers with PHP post for more details).

The above example would output the following from my own data as at the time of writing this post.

/jquery-get-set-form-values/ 87.17%
 /article/apache/restart-apache/ 94.31%
 /article/mysql/delete-all-data-mysql/ 91.23%
 /php-http-referer-variable/ 92.74%
 /check-uncheck-checkbox-jquery/ 86.73%
 /article/mysql/cross-table-update/ 88.99%
 /article/networking/open-firewall-msn-icq/ 94.37%
 /article/linux-unix-bsd/howto-check-md5-file/ 94.75%
 /upper-lower-case-strings-mysql/ 95.69%
 /install-yum-with-rpm-on-centos/ 87.36%

The defaults for the ->data() method will get data for the month to yesterday and for the first 10 records only. This can be modified to a different date range and/or number of records. For example, to get the same data for 1000 records for the same date range you could do this:

$data = $api->data($id, 'ga:pagePath', 'ga:bounces,ga:uniquePageviews', '', '', '', 1000);

I’ve realised in writing this I don’t actually have a post dedicated to the parameters for the data call so will write one and post it tomorrow.

Read More »

var_dump or print_r inside a Smarty template

While trying to debug why something wasn’t working, I needed to see what data had been assigned to a Smarty template but from within the template itself (I didn’t have time to try and work out where in the PHP code the stuff was assigned and debug from there). This post shows how to do a var_dump or print_r from within the Smarty template itself.

Read More »

PHP parse_url error for https requests from “Test Certificate Info”

The PHP websites I manage email me all notices, warnings and errors and I occasionally get warnings resulting from bots requesting bad URLs. This post looks at a PHP parse_url error caused by an incorrect piece of code that was published which has since been corrected, but there are clearly still scripts out there using the old code and making bad requests.

Read More »

Paging through result data from the Google Analytics API PHP Class

I had a query the other day about paging through Google Analytics API data using my PHP Class; Google allows a maximum of 1000 records to be returned at a time per request so you need to loop until there’s no more data, requesting 1000 records at a time starting from offset 1001, 2001 etc.

Read more about my Google Analytics API PHP class and download the class and example files.

data method parameters

The ->data() method takes a number of parameters which are as follows (I may modify the class (or rewrite) at a later date to make these class properties instead of having so many parameters passed to a function call):

  • $id – the profile id to query data for
  • $dimension – the dimension(s) to retrieve data for
  • $metric – the metric(s) to retrive data for
  • $sort – the sort order for data
  • $start – the start date in YYYY-MM-DD format
  • $end – the end date inYYYY-MM-DD format
  • $max_results – the maximum number of results to return
  • $start_index – the index to start from, if $max_results is 1000 then the second “page” of data would have a start index of 1001
  • $filters – information to filter the data
  • $debug – if true will echo out the URL that is called when asking Google for data

Looping until the end of data

The following data call will get the page path and number of pageviews for all data in a specified date range (last month as of the writing of this post). It then loops through the data returned from Google until there is no more.

$data = true;
 $index = 1;
 $increment = 1000;
 while($data) {
 $data = $api->data($id, "ga:pagePath", "ga:pageviews", "", 
 "2009-05-01", "2009-05-31", $increment, $index);
 // do something with the data here
 $index += $increment;

$data is set to true before the loop so it will loop at least once. You could equally do a do { } while() loop and not set $data before the loop but I’m not a fan of do … while.

$index is the index to get data from. It’s incremented at the end of each loop by the $increment amount.

$increment is the number of rows to get each time and also the offset to add to $index at the end of each loop.

When no more data comes back from the GA API while($data) will evaluate to false and the loop will end. Of course, if you have a lot of data for the selected dimension(s) and metric(s) it may take a long time for this to run. You may want to limit the number of queries instead of going for all data in this instance.

Read More »