Mar 302011

1. Installation
Create a file “package.json” with the following content (set uid of your package)
"uid": "(your package uid)"

Create a file called “package.json” with with content as example below (add IP restriction or/and keys), the example gives unlimited access.
"": {
"allow": {
"ips": [ "*" ],
"authkeys": [ "*" ]

Download the server library, the easiest is to use phar file, and set up your virtual host:
<VirtualHost *:80>
php_value auto_prepend_file phar:///var/www/firePHP_1.0/firephp.phar/FirePHP/Init.php
SetEnv INSIGHT_CONFIG_PATH /var/www/firePHP_1.0/package.json,/var/www/firePHP_1.0/credentials.json

Install client plugin (FirePHP Companion) in your web browser,

2. Page Context
$inspector = FirePHP::to("page");
$console = $inspector->console();
$console->log("Hello World");

3. Request Context
$inspector = FirePHP::to("request");
$console = $inspector->console();
$console->log("Hello World");

4. Controller Context
$inspector = FirePHP::to("request");
$console = $inspector->console();
$console->log("Hello World");
$controller = FirePHP::to("controller");

5. Package Context

$package = FirePHP::to("package");
$package->addQuickLink("Link 1", "");
$package->addQuickLink("Link 2", array(
"target" => "window", // tab (default), window or hidden
"url" => ""

$controller = FirePHP::to("controller");

6. Basic API
$inspector = FirePHP::to("request");
$console = $inspector->console();
$variable = "Hello World";


// Message Label
$console->label("My label")->log($variable);

// Table
$header = array("Column 1 Heading", "Column 2 Heading");
$table = array(
array("Row 1 Column 1 Value", "Row 1 Column 2 Value"),
array("Row 2 Column 1 Value", "Row 2 Column 2 Value"),
$console->table("Table", $table);
$console->table("Table with header", $table, $header);

// Stack Traces
$console->trace("My stack trace");

// Group
$group = $console->group("myGroup", "Group Title")->open();
$console->info("Hey!, I am in a group");
$console->error("I am in a group too!");

// Console controller
$controller = FirePHP::to("controller");

7. Conditional Logging

$inspector = FirePHP::to("request");
$console = $inspector->console();

$console->on("Show warnings")->warn("I am warning you!");

// Console controller
$controller = FirePHP::to("controller");

8. Engine API
$inspector = FirePHP::to("request");
$console = $inspector->console();
$engine = FirePHP::plugin("engine");
// Send all exceptions and errors to a specific console
// Console controller
$controller = FirePHP::to("controller");

// Handle manually
try {
throw new Exception("Hello, I am a manually handled exception");
} catch(Exception $e) {

throw new Exception("Test Exception");

9. FirePHP API
$inspector = FirePHP::to("request");

// Log p() messages to the provided console
$firephp = FirePHP::plugin("firephp");
$inspectorConsole = $inspector->console("InspectorConsole");
$firephp->declareP($inspectorConsole, true);

$variable = array("key"=>"value");
p($variable); // or
p($inspector, "Inspector");

// Log the current FirePHP version to a FirePHP console.
$versionConsole = $inspector->console("Version Console");

// Send information about the PHP environment to an Environment console.
$envConsole = $inspector->console("Environment");

// Console controller
$controller = FirePHP::to("controller");

//Send all errors and exceptions to a Problems console.
$problemConsole = $inspector->console("Problem Console");

throw new Exception("I am your problem");

Mar 302011

1. FirePHP 0.5 – Installation
1. Dwonload The Server Library and include it
2. require_once("./FirePHPCore-0.3.2/lib/FirePHPCore/FirePHP.class.php");
Or find a plugin for your framework.

2. Object Oriented API
$firephp = FirePHP::getInstance(true);
$firephp->log("Hello World");

3. Procedural API
fb("Hello World");
fb("Hello World", "Label");

4. Options

// Defaults:
$options = array("maxObjectDepth" => 5, // Maximum depth to traverse objects.
"maxArrayDepth" => 5, // Maximum depth to traverse arrays.
"maxDepth" => 10, // Maximum depth to traverse mixed arrays/objects.
"useNativeJsonEncode" => true, // Set to FALSE to use JSON encoder included with FirePHPCore instead of json_encode().
"includeLineNumbers" => false); // Include File and Line information in message

$firephp = FirePHP::getInstance(true);
$firephp->log("Hello World");

5. Log level

$firephp = FirePHP::getInstance(true);
$firephp->log("Logs a message to firebug console.");
$firephp->info("Logs a message to firebug console and displays an info icon before the message.");
$firephp->warn("Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise.");
$firephp->error("Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count.");
// or
$firephp->fb("Log with fb() method", FirePHP::LOG);
$firephp->fb("Info with fb() method", FirePHP::INFO);
$firephp->fb("Warning with fb() method", FirePHP::WARN);
$firephp->fb("Error with fb() method", FirePHP::ERROR);

6. Dump

$firephp = FirePHP::getInstance(true);

7. Trace

$firephp = FirePHP::getInstance(true);
$firephp->trace("Trace Label");

8. Groups

$firephp = FirePHP::getInstance(true);
$firephp->group("Test Group");
$firephp->log("Hello World");

$firephp->group("Collapsed and Colored Group",
array("Collapsed" => true,
"Color" => "#FF00FF"));
$firephp->log("Hello World");

9. Tables

$firephp = FirePHP::getInstance(true);

$table = array();
$table[] = array("Col 1 Heading","Col 2 Heading");
$table[] = array("Row 1 Col 1","Row 1 Col 2");
$table[] = array("Row 2 Col 1","Row 2 Col 2");
$table[] = array("Row 3 Col 1","Row 3 Col 2");

$firephp->table("Table Label", $table);

10. Exception Handling

$firephp = FirePHP::getInstance(true);
$firephp->registerErrorHandler( $throwErrorExceptions=false);
$firephp->registerAssertionHandler( $convertAssertionErrorsToExceptions=true, $throwAssertionExceptions=false);

throw new Exception("Test Exception");
// or manually
try {
throw new Exception("Test Exception");
} catch(Exception $e) {

11. Disabling firePHP

$firephp = FirePHP::getInstance(true);
$firephp->log("Hello again");

Apr 142009

DB2 is one of IBM’s database server systems, it comes in many flavours, and runs on many platforms including Linux and Windows, but traditionally on IBM’s own mainframes. DB2 has a long history, so if you’re in the business chances are you’ll need to work with it one day.

We bumped into it when we had to connect to said database across both platforms and network. Here’s an account of our experience with it.

The problem

A web application in a LAMP environment (Ubuntu Hardy, Apache 2, MySQL5 and PHP 5.2), where login should be done using a centralised database – the already mentioned IBM DB2, on IBM System i.  As with DB2, System i has a long history, so don’t be surprised if it’s referred to by previous names such as AS/400, or eServer iSeries.

The solution

Our first attempt involved installing DB2 express on the same server as the web application, by using the ibm_db2 driver we got a connection that worked, but we were denied access with the following message:

An attempt to connect to a host failed due to a missing DB2 Connect product or invalid license. SQLSTATE=42968

DB2 Connect is apparently part of some DB2 products, but not DB2 express. A long call to IBM eventually established that we probably needed to pay for this approach to work.

Second attempt

Luckily there is another way to connect to DB2 – using ODBC. Which means we need an ODBC driver for DB2. IBM calls System I Access a connectivity product, and its web page goes on to say: “The entire focus of System i Access is to deliver the strengths and capabilities of System i to the desktop through easy-to-use screens and wizards”. In short, it’s a bundle that includes a 5250 emulator, an EDRS driver, and what we need: an ODBC driver.

  • Get ODBC: We need an ODBC manager and PHP support for it. Download and install it by apt getting unixodbc, unixodbc-bin, php5-odbc and libstdc++5.
  • Get System i Access: We also need an ODBC driver for DB2, available for dowload free of charge as an RPM package from Remember to choose the correct version for your system (32-bit or 64-bit). To install it you can for instance run the following:

$ sudo rpm -ivh –nodeps iSeriesAccess-5.4.0-1.6.i386.rpm

It will be set up under the catalogue /opt/ibm/

The ODBC manager needs to know about the odbc driver and what to say to it. This is configured in two files: odbc.ini and odbcinst.ini. If they haven’t already been created by installing System i Access, they should be created in the /etc folder.

odbc.ini should look something like this:

Description             = iSeries Access ODBC Driver
Driver                  = iSeries Access ODBC Driver
Driver64                = iSeries Access ODBC Driver 64-bit
System                  =
UserID                  = ELVIS
Password                = PRICILLA
Naming                  = 0
DefaultLibraries        = HAWAII,QGPL,qiws
Database                = GRACELAND
ConnectionType          = 0
CommitMode              = 2
ExtendedDynamic         = 1
DefaultPkgLibrary       = QGPL
DefaultPackage          = A/DEFAULT(IBM),2,0,1,0,512
AllowDataCompression    = 1
MaxFieldLength          = 32
BlockFetch              = 1
BlockSizeKB             = 128
ExtendedColInfo         = 0
LibraryView             = 0
AllowUnsupportedChar    = 0

Each connection has its own ini section. The following parameters are the ones you are most likely to change:

  • Driver: has to match a section in odbcinst.ini, which we’ll get to shortly.
  • System: The ip adress to where the db2 is
  • UserID
  • Password
  • DefaultLibraries: QGPL and qiws are standard, but most likely you need extra libraries
  • Database: The name of the database you want to connect to

odbcinst.ini should look something like this:

[iSeries Access ODBC Driver]
Description     = iSeries Access for Linux ODBC Driver
Driver          = /opt/ibm/iSeriesAccess/lib64/
Setup           = /opt/ibm/iSeriesAccess/lib64/
NOTE1           = If using unixODBC 2.2.11 or later and you want the 32 and 64-bit ODBC drivers to share DSN’s,
NOTE2           = the following Driver64/Setup64 keywords will provide that support.
Driver64        = /opt/ibm/iSeriesAccess/lib64/
Setup64         = /opt/ibm/iSeriesAccess/lib64/
Threading       = 2
DontDLClose     = 1
UsageCount      = 1

[iSeries Access ODBC Driver 64-bit]
Description     = iSeries Access for Linux 64-bit ODBC Driver
Driver          = /opt/ibm/iSeriesAccess/lib64/
Setup           = /opt/ibm/iSeriesAccess/lib64/
Threading       = 2
DontDLClose     = 1
UsageCount      = 2

Notice there’s no mention of port anywhere. You cannot configure this, the port is 8471 so make sure it’s open in both ends. Also note that the Driver and Driver64 parameters in odbc.ini matches the two sections in odbcinst.ini


Using the connection
The setup should be up and running now, so to use it in PHP we need to create a connection. A simplified connection can look something like this:

function getConnection()
$dsn             = sfConfig::get(‘db2_conn_dsn’, ‘DB2CONN’);
$user            = sfConfig::get(‘db2_conn_usr’, ‘ELVIS’);
$pwd             = sfConfig::get(‘db2_conn_pwd’, ‘PRICILLA’);

$connection = odbc_connect($dsn, $user, $pwd) or die ("Can not connect to $dsn.");

return $connection;

An example of a simple login query that uses a stored procedure from the hawaii library:

function checkUserNameAndPassword($username, $password)

$conn            = getConnection();
$user            = false;
if ($conn)
$sql       = utf8_decode("{CALL HAWAII.LOGIN(‘$username’, ‘$password’)}");
$callstore = odbc_exec($conn, $sql) or die ("Can not perform query");
$user    = odbc_fetch_array($callstore, 1);

return $user;

For debugging purposes, a useful way to output the result from an odbc_exec can be found in one of the comments at:


Here’s a simplified example of how to insert data using a prepared statement:

function insertUser($user)

$conn = getConnection();

$sql .= utf8_decode(" VALUES (?,?,?,?)");
$res  = odbc_prepare($conn, $sql) or die ("Can not prepare query");
$parameters = array(
if(!odbc_execute($res, $parameters)) die("Can not perform query");

return true;

You can also insert without using the prepare statement (by using odbc_exec), but we had trouble with character encoding. The example above worked for us.


Good luck!