On PSR-0 standards, namespaces and code (re-)use
When it comes to working on several projects with different people, having a set of standards to dictate code use and code re-use is a good thing to have. PSR-0 is one such accepted standard.
It took a while to realize it, as I so often do, that many useful improvements to PHP mean a few steps forward, a few steps back. I’m going to try to list a few patterns which are the cause of some conflict when implementing PSR-0.
Global variables are bad
It’s a widely accepted programming pattern in PHP that global variables are bad. Using global variables is a so called anti-pattern, it’s use greatly discouraged and frowned upon. From what I remember, the main cause of this being discouraged over time was because of the “register_auto_globals” option PHP had offered. Using it was the cause of many notable security flaws in software all around.
Many other reasons exists for the case why you shouldn’t use global variables - but there is a need to share objects and variables between various places in any code base. Avoiding global variables makes this kind of sharing significantly clearer and comes with some other benefits too.
Static class methods
Using static class methods is a way to avoid using global variables. Instead of storing your objects, configuration and what-have-you in the global scope, you could store it in a short named class as a static value. This gives you the benefit of using “config::get(‘language’)” or “registry::get(‘database_connection’)”. Having a minimal and solid implementation of common and widely used static objects is highly expressive and useful.
Namespaces and PSR-0
According to the PSR-0 document, the classes must be declared as [<Vendor Name>(<Namespace>)<Class Name>]. This encourages code re-use, but it only does this by actually encouraging instances - with little or no thought given to static objects that could be shared across your whole project, like a global function or a static container class would be.
The kludge to work around this is to declare a minimal class in your project that just extends the full namespaced PSR-0. The other ways have significant caveats. I say kludge because this appears to be the only way to create a global class scope with namespaces.
The example [\vendor\namespace\config::get(“language”)] call illustrates how “hard” it would be to use a name-spaced static object across your project. You can always fall back to creating an alias with [use \vendor\namespace\config;] and use [config::get] as you did before - but with having to declare usage in every file you do this.
Ideally, a way to declare a global class alias would be a “clean-er” way to solve this; but as far as I know, this steps further away from traditional namespaces in other languages. Changes like this are something the PHP developers have been strongly against from the start - and I don’t expect that to change any time soon.
The PSR-0 is a seminal document in the way it encourages code re-use, but falls short when it comes to actual shared use of this code. Absolutely no thought has been given to static-access patterns with PSR-0, and I don’t see a nice way of reconciling this because of issues inherent with the implementation of PHP namespacing, especially it’s aliasing features. PHP is trying too hard to be “enterprise” to realize that being “enterprise” actually means abandoning the simplicity and expressiveness that are, in my eyes, a few of the reasons that PHP became so popular in the first place.
Many projects don’t have a share-nothing architecture which PSR-0 encourages. If you’re considering adopting PSR-0 as your standard of choice, you must do so with some thought - the stylistic parts of the higher numbered PSR-[1,2] standards afford some benefits when working with several programmers in teams, but implementing PSR-0 comes with some significant caveats that imply that some common practices in the PHP community are now considered anti-patterns.
Composer and Packagist
If you’re still considering using PSR-0 or even if you’re not, there are a few projects that make your life a little bit better. You can use composer to provide an update mechanism for your shared code between your projects. You can use public Packagist repositories, or you can create your own with any of these: Packagist, Satis or my own Composer-sentinel.
May all your code be great.
- Tit Petric