autoload conflicts

Our publishing system has a fairly large PHP object model, with tons of corresponding library files. Early in the development of the library, we saw huge value in PHP 5’s autoloader. But when we integrated a 3rd party library into our application, we quickly found a limitation when our __autoload() function conflicted with the other library’s __autoload() function.

In PHP 4 and earlier, if you had a large class library defined across a number of class files, you were responsible for making sure that the proper files were loaded via calls to require(). An application script might have 15 or 20 require() calls. You might have worried about requiring files more than once. To get around that, you might use require_once(), or you might avoid defining classes more than once by using some ugly conditionals in your class files. You might end up with lots of wasteful calls to require_once(), which could hurt performance.

Enter the autoloader. In PHP 5, you can define an __autoload() function, which helps PHP find the proper library files to require when it encounters an unknown class. A typical __autoload() function might look like:

When you make a call like:

PHP will call the autoloader with $class_name = “foo”. The example implementation will then require “lib/foo.php“. You can get much fancier with your autoloader — you can check for existence of files before blindly require-ing them. You could handle nested directories in your library by converting underscores in the class name to directory delimiters (e.g., “mylib_model_foo” would translate to “mylib/model/foo.php“).

This is all well and good, and it makes your library code quite clean. But what happens when you try to use a third-party library that also defines an __autoload() function? You’ll get a nasty error like this:

Obviously, you won’t get far with two __autoload() functions defined. How can you get around this?

If you’ve got some control over the third-party library, you could chain your autoloaders. For example, suppose your code is in my_library.php and the third-party library is in third_party.php.

In my_library.php:

Now in third_party.php:

This works reasonably well. When you’re using your own library indepedently of the third-party library, it will use your autoloader as normal. When you load in the third-party library, make sure you load it first so it can define __autoload() before your code tries to do so. Note that if your class library uses any of the same class names as the third-party library, you’ll have to deal with that separately. Unfortunately, there’s no good fix for that problem. This is one of those situations where it is helpful to prefix your class names with a special string to avoid naming conflicts.

Another interesting approach is to use spl_autoload_register(), a function in the Standard PHP Library. If your PHP has the SPL module installed, you can make use of this function. It allows you to register an autoloader function (which can be a class method) for your library. This function should return true if it is able to load the appropriate class file, or false otherwise.

Other libraries can also register their autoloaders.   The SPL autoload mechanism will call the functions in the order in which they were registered until one of them returns true.  Note that you may have some performance considerations.  If the bulk of the objects you’re using come from one particular library, you’ll want to make sure that its autoloader is registered first.  Otherwise, you’ll be making a lot of wasted calls to the other libraries’ autoloaders.

The SPL autoload registration system allows multiple libraries to play nicely with one another.  But it will require widespread adoption for it to truly be effective in ending autoloader conflicts.

Leave a comment

Your email address will not be published. Required fields are marked *