The Joomla! ® Community Magazine

Rapid Development Techniques - Preventing Code Fragmentation

Written by Jarrod Nettles | Wednesday, 01 December 2010 18:39 | Published in 2010 December
Level of Difficulty:Intermediate 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 16813 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.

Leave a comment

Make sure you enter the (*) required information where indicated.

[b] [i] [u] [s] [url] [quote] [code] [img]   

Comments (9)

  • avatar
    • 2
    • 2
    Nicholas K. Dionysopoulos

    That's an unproductive way to do that, to say the very least. Down the road it will cause havoc, unless you remember to meticulously fix all jimport calls before shipping that code to the public. If not, you have to create an overly complex installation procedure which installs MyLib in a subdirectory of the libraries directory, which opens up a whole new can of worms when performed on slow shared hosts which have never heard of suPHP before...

    I always like to keep things simple. Why don't you just use symbolic links (Hard Link Shell Extension on Windows, ln -s on Linux, Mac OS X, BSD and any other UNIX system)? All you need to have is one copy of your PHP files and symlink them to wherever you want on each test site of yours. This technique is well tested, at least for 3 years by yours truly – and much longer by others. It works cross-platform, requires no code modifications and is very flexible, especially if you want to move things around and not have to grep your code for a gazillion of jimport instances.

  • avatar
    • 1
    • 0
    Jarrod Nettles

    I mentioned in the article that this technique requires no code modification when shipping to production. All it requires is exporting the library into the "libraries" directory of the Joomla install and all jimport calls will work without any modification.

    Also, I think your point of view here is being colored by strictly third-party extension development. There are plenty of in-house/private developers out there who wouldn't have a problem with creating additional libraries since they're in full control of the entire installation.

    I appreciate the comment though, it had never occurred to me to symlink. It would definitely be useful in not having three separate Joomla installs on my development machine.

  • avatar
    • 0
    • 10
    Web Design & Development Compa

    Hi There,
    We have Designed and Developed several websites and portals for clients from different countries.

    Thanks,
    Mick

  • avatar
    • 3
    • 0
    Adam Docherty aka Lobos

    One could also bundle the libraries into a plugin. You could then load the plugin and use a wrapper, singleton type factory function to call the library you need.

    The great thing about this is that you can easily upgrade your libraries via Joomla's installation system.

  • avatar
    • 1
    • 0
    Giuseppe

    Merry christmas and happy new year

  • avatar
    • 1
    • 0
    Erez Avny

    Why don't use

    Code:
    JLoader::import('mylif','/var/www/')

    instead the hack the Joomla Core?

  • avatar
    • 0
    • 0
    Custom Web Application Develop

    Hi There,
    In the development business for awhile then you probably have a substantial library of code that you frequently .
    Nice post Thanks,
    Alman

  • avatar
    • 0
    • 0
    almamun

    enter your message here...

    Erez Avny wrote:
    Why don't use
    Code:
    JLoader::import('mylif','/var/www/')


    instead the hack the Joomla Core?

    What the experts say???

  • avatar
    • 0
    • 0
    bandar

    مقبل على تركيب نسخة الموقع جملا قريبا و قد اخرني عن اتخاذ القرار و البدأ في التركيب عدم وجود امكانية التعليق في نسخة الموقع جملا 1،5 لذا ارجوا ان يكون هناك حلاً تعليقات المستعملون و الزوار كما هو الحال هنا