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.
{
"cadorn.org/insight/@meta/config/0": {
"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
...
</VirtualHost>

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");
$controller->triggerInspect()


5. Package Context

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


$controller = FirePHP::to("controller");
$controller->triggerInspect();

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

$console->log($variable);
$console->info($variable);
$console->warn($variable);
$console->error($variable);

// 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!");
$group->close();


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

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");
$controller->triggerInspect();

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

// Handle manually
try {
throw new Exception("Hello, I am a manually handled exception");
} catch(Exception $e) {
$engine->handleException($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");
$firephp->logVersion($versionConsole);

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

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

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

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
require_once("./FirePHPCore-0.3.2/lib/FirePHPCore/FirePHP.class.php");
$firephp = FirePHP::getInstance(true);
$firephp->log("Hello World");

3. Procedural API
require_once("./FirePHPCore-0.3.2/lib/FirePHPCore/fb.php");
fb("Hello World");
fb("Hello World", "Label");

4. Options
require_once("./FirePHPCore-0.3.2/lib/FirePHPCore/FirePHP.class.php");

// 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->setOptions($options);
$firephp->log("Hello World");

5. Log level
require_once("./FirePHPCore-0.3.2/lib/FirePHPCore/FirePHP.class.php");

$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
require_once("./FirePHPCore-0.3.2/lib/FirePHPCore/FirePHP.class.php");

$firephp = FirePHP::getInstance(true);
$firephp->dump("array",array("key"=>"value"));
$firephp->dump("firePHP",$firephp);

7. Trace
require_once("./FirePHPCore-0.3.2/lib/FirePHPCore/FirePHP.class.php");

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

8. Groups
require_once("./FirePHPCore-0.3.2/lib/FirePHPCore/FirePHP.class.php");

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

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

9. Tables
require_once("./FirePHPCore-0.3.2/lib/FirePHPCore/FirePHP.class.php");

$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
require_once("./FirePHPCore-0.3.2/lib/FirePHPCore/FirePHP.class.php");

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

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

11. Disabling firePHP
require_once("./FirePHPCore-0.3.2/lib/FirePHPCore/FirePHP.class.php");

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

Feb 072011
 

The Bug Genie version 3.0 released

Last week, The Bug Genie 3.0 was released, together with an updated website.

The Bug Genie is a PHP-based issue tracker and project management tool in development since 2002. Version 3.0 is based on PHP 5.3 and has been in development since late 2009.

Visit http://www.thebuggenie.com for more information!

v3

Jan 242011
 

The PHP competence group is proud to announce that our company Redpill Linpro will be Gold Sponsors of this year’s Symfony Live conference in Paris. We have instigated this sponsoring as we are, and have been, proud users of the framework for our customers for years. Pages we have created with symfony include everything from media based and content driven applications, to membership systems, and even SMS-handling. This is one of our ways of contributing back to a great OSS PHP project.

We are in the planning phase as of now, and have not yet decided what we should do to get attention at the conference, but there will definitely be booth-boys, give-aways and probably a competition. Do you have any booth attraction top tips for us?

Do not forget to check out our main Symfony contributor’s post about the sponsoring on his own blog.

Nov 252010
 

update: The contents of this blog post has now been merged into the Doctrine 2 cookbook entry (http://www.doctrine-project.org/docs/orm/2.0/en/cookbook/sql-table-prefixes.html)

A few months ago, we started using Doctrine 2 on the project we’re developing for a customer of ours. Doctrine 2 has proven to be both fast and stable which has certainly saved us time and effort. We recently had to implement table prefixes on our tables in Doctrine 2, which turned out to be not so trivial, and led me to a journey inside the Doctrine 2 metadata parser, event hooks and relation mapper. Fun stuff!

Prefixing regular tables

The first thing I had to do was to get prefixes working. Contrary to Doctrine 1, where you could use the Doctrine_Core::ATTR_TBLNAME_FORMAT to set a table prefix (or suffix), there isn’t yet a similar feature for Doctrine 2 (looking at some bug reports like this one, it doesn’t look like it’s high up on the list of priorities either). However, the solution suggested was to add a loadClassMetadata listener to provide the table prefixes by rewriting the defined table names as they were being generated and add the prefix programatically in that event. The cookbook entry describes the procedure for implementing this in detail, and after adding the suggested lines of code to our Doctrine loader tables were being prefixed all around.

Prefixing many-to-many jointables

However, the many-to-many automatically generated jointables were *not* being prefixed, and there turned out to be a good explanation. The loadClassMetadata event was being fired in the table that defined the many-to-many joined relations, but there was no separate loadClassMetadata event fired for the generated jointables where I could rewrite the table name with the configured prefix. As Benjamin Beberlei mentioned in a follow-up comment to the bug report we filed for the cookbook entry, this was both (semi-)intended behaviour and a known limitation of the code in the cookbook entry with an “easy” fix. The fix meant I had to look into taking a peek at the table’s metadata and perform an explicit rewrite on the related jointable. Luckily that’s all documented behaviour and the pointers Benjamin gave me were more than enough to get me started.

The behaviour of the code in the cookbook was to just get the table name from the class metadata as it was being loaded, prepend the table prefix and set the table name back to the new prefixed name. Easy peasy.

$classMetadata = $eventArgs-&gt;getClassMetadata();
$classMetadata-&gt;setTableName($this-&gt;_prefix . $classMetadata-&gt;getTableName());

However, to rewrite the table name for many-to-many relation jointables, we have to also traverse the classmetadata properties, look for related tables and rewrite them if the join type is many-to-many:

foreach ($classMetadata-&gt;getAssociationMappings() as $fieldName =&gt; $mapping) {
if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY) {
$tableName = $classMetadata-&gt;associationMappings[$fieldName]['joinTable']['name'];
$classMetadata-&gt;associationMappings[$fieldName]['joinTable']['name'] = $this-&gt;_prefix . $tableName;
}
}

Turns out that it wasn’t that much effort needed, and the result is neatly prefixed table names all around. As an extra, we of course also added a ZF application.ini entry to define the table prefix for easy configuration. But that’s a different blog post.