PSR-0: Great Idea, Bastardised Execution

If there’s one thing PHP needs, it’s a bit more convention. Node and Ruby can both attribute a large portion of their success to their respective package managers. Unfortunately PHP has such a… diverse history that using different components between frameworks and projects often requires a cumbersome set of differing bootstraps and loaders. PSR-0 looked set to be at least a partial solution; a common naming convention such that files could be loaded in the same way, regardless of their original framework. And they royally screwed it up.

I know I’m a bit late to the party, but like all people I only started to moan when it started to affect me. My framework of choice, Kohana, added PSR-0 compliance to the 3.3 development branch. And broke how every existing user expected the framework to work.

Firstly a bit of background on what PSR-0 actually it. PHP Standards Recommendation 0 is a guideline for how classes, their files and autoloaders should work to ensure harmony between projects. Set up by a group called FIG (supposedly made up of the major framework players, but with little in the way of online presence) it’s become so much of a standard now that PHP itself is deciding whether to include it in the core SPL. At it’s most basic if you have the class foo_bar, the autoloader should look in foo/bar.php for the class definition. Simple. Underscores (and namespaces) become directories and the last part becomes the filename.

Except once again PHP’s history rears its ugly head. You see, in PHP Foo and foo and FOO all represent the same class. That’s right, functions and variables are case sensitive, but not class names. There are reasons for this, and it can actually be useful (especially when dynamically generating class names in routing libraries and drivers), but ultimately this is something that cannot change without risking breaking all existing projects. So what to do?

The logical choice is simple: normalize all class names when generating file paths, typically by lowercasing the class name first. So Foo_Bar, foo_BAR and FoO_bAr should all look in foo/bar.php. And this is exactly what Kohana and a dozen other frameworks did. But they didn’t write PSR-0, the big boys did; Zend, Symfony et al. And they decided to do things “the correct way” i.e. the way they’d been doing it for years.

So, what’s the problem you might ask? Just name your files the same way. Great! Until you start hitting the edge cases. Calling “new foo()” after calling “new Foo” would work, but swap the order of those two arguments and suddenly your code breaks. Or even better, develop on a local filesystem that’s case insensitive by default e.g. OS X/HFS+ and then deploy to a live server and watch everything crumble before your eyes.

The solution to this was so simple; a single call to strtolower(). Tools like Git make it ridiculously easy to rename files and preserve history. Instead, we now have to refactor code to ensure every call represents the same class. If we want “pretty URLs” with dynamically extracted controllers, we now need to start breaking naming conventions e.g. Controller_BlogPost would only match /BlogPost/view/123 so now you end up with classes such as Application_Controller_blogpost.

This is the first time I’ve felt motivated enough to write about something in the PHP community. I can take all the stick from other languages, I can get over the haphazard naming conventions, but this? Right when PHP was moving in the right direction they go and screw it all up. If PSR-0 gets included the SPL autoloader it’ll be game over. Thanks for reading.

  • 5 apr 23:43