The Joomla! Community Magazine™

Rapid Development Techniques - Preventing Code Fragmentation

Written by | Wednesday, 01 December 2010 18:39 | Published in 2010 December
If you’ve been in the development business for awhile then you probably have a substantial library of code that you frequently use. It’s your work belt, your briefcase, your attaché that follows you into whatever project that you happen to be working on. You know, trust and love your code base because you wrote it and understand it intimately. Whether another developer would consider it up-to-standards or pretty is irrelevant — it works and so you use it whenever and wherever you can. It helps you follow that sacred tenet of programming, Don’t Repeat Yourself, that we all hold dear.

Let me paint a situation for you

You’ve been working on a project and over time you have developed a strong library of code. As time goes on you need to create a separate project for a separate site. Suddenly you need two copies of your library, one in each project! No problem, you might say — I’ll just make sure that whatever changes I make in one, I make in the other. A third project? A fourth? No. Right here, right now, I can unequivocally tell you that this will not work. You might keep it up for a couple of days but I can tell you from experience that this quickly breaks down (I won’t even begin to address the complexities of this if you add another developer to the mix — the problem grows exponentially for each programmer that you add). The building crumbles, the waveform collapses, seas rise, nations fall — you get the idea. Your library is fragmented and useless.

The obvious solution is to have a single copy of your library that all your projects use — the question is: how do I include those files without having complicated require_once statements all over the place? If you’re like me then you actually enjoy using jimport, which invokes in me a feeling that I’m working in a package-based environment like Java or .NET. It also makes perfectly clear what class files you’re using and their directory path.

Note: Purists will argue that jimport is a global function and therefore sinful; indeed, jimport is nothing more than a wrapper for the JLoader class, providing a quick path to including files without having to type out JLoader::import().

So you’ve decided to go ahead with the single library solution — how do you arrange things so you don’t have to alter your existing projects' code to accommodate the new directory structure? First, let’s take a look at how your projects are organized (I’ll be using Linux as an example here, though you can easily adapt this to Windows or Mac). Let’s say my development machine looks like this:

/var/www/AlphaProject
/var/www/BetaProject

Those are both full Joomla installs with their own copy of my custom library, MyLib.

/var/www/AlphaProject/libraries/MyLib
/var/www/BetaProject/libraries/MyLib

Note: I’m using Zend Studio while preparing these instructions. Eclipse users should be able to follow along without much trouble.

Go ahead and make a copy of your library, and then remove it from each project’s directory structure. It will be finding a new home in a moment. Create a new project in your root directory structure, called MyLib. For the sake of simplicity I’m going to assume that this will be the only library you have; if you have multiple custom libraries that you import from you can certainly create a generic Libraries project with each individual library inside the project.

Our library now has a new home — /var/www/MyLib — and is sitting there waiting to be used. How do we tell jimport to target this folder when necessary? To do this, we make a small core hack.

Note: Before you form into an angry mob with pitchforks and torches over suggesting a core hack, know that this change only needs to be made on your development machine. So long as your production web site has a copy of the library on the regular directory structure of /site/libraries/ then your production code will require no modification.

Navigate to the joomla/libraries folder and open up “loader.php”. This file is responsible for all file loading in the Joomla! framework, so we need to teach it how to recognize our custom library and give directions on where to find it. We also need to make sure that it doesn't have any problems locating the “joomla” library or any of the others that are in the default installation.

Scroll all the way to the bottom and you'll see the infamous “jimport” function. Calls come into jimport like this:

jimport( 'joomla.application.component.controller' );

The first segment, “joomla”, is the library name on the /joomla/libraries directory path. We need to catch this and check to see if we're trying to call our own library. Modify jimport so that it looks like this.

function jimport( $path ) {
$parts = explode('.', $path);
if($parts[0] == 'MyLib')
{
return JLoader::import($path, '/var/www');
}
else
{
return JLoader::import($path);
}
}

What have we done?

We've caught all incoming jimport calls and split them apart to check and see if the library call is intended for MyLib. If it isn't, we just go right ahead with standard operating procedure. However, if the first segment matches “MyLib” we go ahead and point JLoader toward our project directory path.

jimport( 'MyLib.Views.FormView' );

will be routed to:

/var/www/MyLib/Views/FormView.php

Note: If you're looking for a challenge, rewrite things so that your jimport() calls are kept in the autoload registry. Classes loaded from outside the joomla library are not currently kept in the registry due to naming convention differences.

You're finished! Visit your development site and check to see that everything is working correctly, and don't forget to copy your library back into the libraries directory of your Joomla! install when you push to production.

Read 23198 times
Tagged under Developers
Jarrod Nettles

Jarrod Nettles

Jarrod is a professional PHP programmer with a focus on frameworks. His everyday work with Joomla! involves extending the capabilities of the MVC framework and developing custom web applications.