Apr 212009
 

In the last few days (evenings) I have been revisiting several games that I found amusing when I was younger. Some of these games I spent endless hours playing – both single- and multiplayer. I also convinced a friend of mine to try playing some of these games with me – apparantly he also enjoyed playing some of them in the past.

As it turns out – these games aren’t as good as they once were. Or – our perceptions, expectations and gaming habits have changed. We want more. The graphical standard – which were breathtaking at the time – now makes the game look old, outdated, boring and uninteresting. The intense gameplay we experienced back then has now turned into boring tasks, repetitive assignments and uninvolving gameplay. The AI is still stunning – although now it is not because it is so good, rather that it is mindnumbingly bad.

Truth be told – I didn’t have as much fun revisiting some of these games as I thought I would.

What on earth does that have to do with PHP? Well, by coincidence, this weekend I also found a backup CD I had lying around – and it had some of my older PHP projects on it. I think you know where I’m going with this now ;)

Yes, you are right – I was amazed by how badly coded these projects were. They are riddled with amateurish mistakes, shortcuts, half-assed solutions and just in general messy code. Functionality that I still remember spending endless hours implementing turns out to be nothing more than semi-intelligent calculations written in poorly designed PHP code.

Notices are being thrown all over the place, short open tags everywhere (and completely at random), $_GLOBALS variables used inconsistently, naming confusion, duplicate functionality in different functions, no classes (well, actually there was one, with one function in it but it wasn’t even used), and no concept of how an application is structured.

Suffice to say I wasn’t as impressed looking at it now, as I was when I was writing it. However – this is a good thing! Spotting obvious mistakes in old code shows that you’ve learnt. I have learnt a tremendous amount of new stuff over the past two, three years, it’s hard to even think about it all!

So – if for nothing else than to give you a good laugh – dig up some old code and have a look at it. Try to remember the good times you had writing it – the challenges you faced and how good you felt when you finally found the ultimate solution. Which turns out was probably not so much the universal ultimate solution, but rather “the best you could come up with, at the time”.

Apr 142009
 

I was working on one of my php free software projects this weekend, and found an interesting bug on one of my pages, resulting in a massive number of database lookups (203 for one page) where ~180 of them was the same “kind” of lookup. Investigating further, I found out that one of my functions which was using isset() was returning a different result than what I would’ve expected.

PHP isset()  has (to me) a very strange behaviour – not only does it check to see if your variable is set (defined), it also wants it to have a specific value. Or, not so much a specific value, but it doesn’t want it to be null. Which means that running:

echo isset($variable) ? ‘yes’ : ‘no’;
$variable = null;
echo isset($variable) ? ‘yes’ : ‘no’;
$variable = ‘anything’;
echo isset($variable) ? ‘yes’ : ‘no’;

will return “no” in the two first cases, while “yes” only on the third attempt.

This is apparently intended behaviour, according to php.net/isset:

Determine whether a variable is set.
If a variable has been unset with unset(), it will no longer be set. isset() will return FALSE if testing a variable that has been set to NULL.

In my case, I was maintaining a $settings array with keys that matched the setting. Instead of loading all settings at startup, I would load the general settings, and only load the user-specific settings on demand. This meant that I would populate the array with keys for the settings that were loaded, as they were loaded. If the key didn’t exist, it would need to look it up from the database. However, a setting can of course be null – in this case that just means that it is not specified for that user (or the general setting was null).

To determine whether a setting was loaded, I then used

if (!isset($settings[$key]))
{
$settings[$key] = doLookupSettingFromDatabase($key);
}

and then return the corresponding setting. This of course works whenever the setting is loaded – unless the setting is null. However, in this case, the array key was actually set – and the value of the key was set, just set to null. The isset() call in this case is a major fail.

In this setting it was a “simple” matter of replacing the isset()-call in the if-test with an array_key_exists()-call, which made the whole thing work as intended. You might also argue the case that I shouldn’t be using isset() in this case, and that array_key_exists() would be the intended function call (as the php docs suggests), but I don’t think that is correct.

I actually like to initialise variables that are later to be used, by assigning them an initial null value – and then if I want to see if I’ve set it to something meaningful, simply call

$variable = null;

{ … snippet of code that might change $variable … }

if ($variable !== null)
{
doSomething();
}

This has worked perfectly for me. I suspect the current isset() behaviour was implemented by someone that thought it was a great idea to implement the same logic in the isset() function. However – there are several situations where a variable would be assigned a null value, and calling isset() on that variable would then return false. In my opinion, a variable is only not isset() if unset() has been called on it. In all other cases, it is set, even if it is set to a null value.

There is of course no fix for this intended behaviour – as changing this isset() behaviour would cause a complete backwards compatibility break – so watch out for those isset() statements.

PS: This flawed logic is not applied to property_exists(). AFAIK, there is no “variable_exists” – this is what isset() is for, and the documentation for property_exists() actually mentions this. Fail x 2, but props for pointing it out in the manual.

PS2: This would probably be a good case to argue the undef data type.

Feb 052009
 

FirePHP is a plugin for the Firebug Firefox extension. Similar to Y!Slow, the plugin hooks into Firebug and provides extra functionality.

Unlike Y!Slow, FirePHP does not create a “new tab” in Firebug. All it does is parse custom HTTP headers and print them out in the Firebug “console” tab. Since the messages have to be sent out as HTTP headers I have never been a great fan of FirePHP, simply because most of the time I would want to inject something to the console tab is looong after I have sent out the initial headers.

After few months of “ignoring the hype” I had to give it a try. My initial testing was just as I expected: This sucks. I had to reorganize all my code so I could send out the FirePHP headers – however doing so had a major impact on when the user got anything back from the page he requested, something I really do not want to do. Bye bye FirePHP.

Here at Redpill Linpro we use Symfony for most of our projects, which uses Output Buffering a lot. Hello FirePHP.

The benefits of using output buffering, among other things, is you can send out headers at any time in the script. That means, we can throw FirePHP messages even in the footers of pages.

So, what is it good for and how do we use it?

AJAX responses have always been a PITA to debug. In some cases we simply do not have any way to print out debug information without destroying the response it self, so we have to turn to flat-file-logging.. which symfony fills up with tons of useless information making it hard to browse. Using FirePHP however you can “print out” whatever information you want, directly to the Firebug console!

Other things like rendering timers, sql queries, backtraces and background info on error pages is great to throw into FirePHP.

To use FirePHP with Symfony you will have to install the Firefox extension itself (duhh) and then the PHP “client library”.
Note: To see the FirePHP messages you will have to enable the “Console”, “Script” and “Net” panels in Firebug!


$ symfony plugin:install sfFirePHPPlugin

The client library is oddly complicated but does do the job. It offers several “importance levels”, which get color coded, such as warnings, info and error. Furthermore you can group messages for easier access.

To, for instance, show the “Symfony Debug toolbar” timers for _all_ requests (including error pages and AJAX responses) you can add to the ProjectConfiguration class:

public function setup()
{
/* [snip] */
if ($this->environment === "dev")
{
$this->getEventDispatcher()->connect("response.filter_content", array($this, "responseFilterContent"));
$this->getEventDispatcher()->connect("application.throw_exception", array($this, "responseFilterContent"));
}

public function responseFilterContent(sfEvent $event, $content = null)
{
$fp = sfFirePHP::getInstance(true);

$fp->group("Debug timers");
foreach(sfTimerManager::getTimers() as $nfo => $timer)
{
$fp->info(sprintf("%s: %.2fms (%d calls)", $nfo, $timer->getElapsedTime() * 1000, $timer->getCalls()));
}
$fp->groupEnd();

return $content;
}

That should give you a nice little groupped “Debug timers” in the Firebug Console using the “dev” frontend \o/.

FirePHP screenshot

You always have FirePHP at your fingertips, to log to it just add

FirePHP::getInstance(true)->info("Hello world! :D ");

Happy debugging!.