Autoloading in PHP 5

Autoloading is a relatively easy concept to understand in PHP 5, but little is talked about it for the newbie programmer or those who are coming up out of PHP 4. It is part of that large group of functions known as “magic functions” and is responsible for getting around that large block of include/require statements you may see at the top of many big PHP scripts. In this entry we will take a closer look at autoloading as it pertains specifically to PHP 5.1+ on this episode of the fabulous life of the Programming Underground!

Some PHP programmers love include statements, some despise them. But the fact remains that they make bigger projects easier to manage (if done correctly). For those who are brand brand new to the language, an include or require function call is a function which goes out and gets another file full of code or definitions and “includes” it in the code before executing. This allows programmers to break up content into separate logical files which come together to fulfill a certain purpose. Perhaps you have a library of functions dealing with strings in one include file, functions to handle numbers in another, and one to handle arrays in another. If your script needs to use strings and numbers, but not arrays, it can include the two files and leave arrays out. Another page may need arrays and numbers, but not strings. You only include what you need.

The difference between include() and its fellow function require() is that require() will create a fatal error on failure. This will force the script to stop processing. So if you need a database connection and use it extensively, you may want to put your database file in a require() call so that if there is an error, your page is not spitting out errors left and right trying to use a database. A similar function is require_once() which will include the file, but only if it hasn’t already been included. This will make sure that only one version of the file is included despite being called in perhaps multiple places.

Ok, so what about autoloading? Autoloading is simply a function that can allow you to load these files dynamically as they are needed. It is named __autoload() and it works like so…

<?php
   function __autoload($filename) {
	  require_once "{$filename}.php";
   }

   $myobject = new myobject();
?>

In the example above, when we try to create an object called “myobject” it will attempt to find a definition for that class. Since it doesn’t find it, it will call the __autoload (notice the double underscore marking this as a magic) function and pass it “myobject” as a parameter. We use that name to construct the require_once() call that includes “myobject.php” in the script. If later I was to use another object like…

   $anotherObject = new otherObject();

… it would attempt to construct that object using a class definition. Since it isn’t found, it will again call the __autoload() function and pass it “otherObject” which would dynamically include “otherObject.php”. That is where I have stored the definition of this object. Hopefully that has come across pretty simple and straight forward. But if you are a seasoned veteran of the dark arts in PHP, you may ask yourself “What if two libraries attempt to define their own __autoload functions? They will get an error for redefining the function!”

Good question and that is why as of PHP 5.1 the gods that be in the PHP universe have created a function called sp1_autoload_register() as part of their SPL (Standard PHP Library) to handle the issue. This function will allow two separate libraries or authors who are designing includes, and want to use __autoload, to register their functions and PHP will use the proper one. Lets take a look at another example…

<?php
   // Our autoload functions
   function my_autoload1_function($filename) {
	  @require_once "{$filename}-example1.php";
   }

   function my_otherautoload1_function($classname) {
	  @require_once "{$classname}-example2.php";
   }

   // Register them using sp1_autoload_register()
   // Pass the function names to this function and it will register the functions.
   sp1_autoload_register('my_autoload1_function');
   sp1_autoload_register('my_otherautoload1_function');

   $myobject = new myobject();
?>

In this example if we attempt to make the object “myobject” and it doesn’t find the class definition, it will attempt to call each of our autoload functions to find it. First it will try “myobject-example1.php” and then it will try “myobject-example2.php”. Our autoload functions also use the @ in front of the require_once calls so that it will suppress any errors in case the file doesn’t exist. It will also allow the script to continue and try the second autoload function.

Now when you use sp1_autoload_register(), you will destroy any __autoload() function you already have defined previously. You may or may not want to do this. So to help check if a previous __autoload() function has been defined, and if it does register it, we can use a little trick of using function_exists().

<?php

   function __autoload($afile) {
	  @require_once "{$afile}.php";
   }

   // Our autoload functions
   function my_autoload1_function($filename) {
	  @require_once "{$filename}-example1.php";
   }

   function my_otherautoload1_function($classname) {
	  @require_once "{$classname}-example2.php";
   }

   // Check to see if we already have an __autoload defined, and if so, register it.
   if (function_exists('__autoload')) {
	  sp1_autoload_register('__autoload');
   }

   // Register the other functions.
   sp1_autoload_register('my_autoload1_function');
   sp1_autoload_register('my_otherautoload1_function');

   $myobject = new myobject();
?>

Now with this example if someone defined an __autoload in the script, and perhaps in separate libraries they created the other autoloads, all three will be registered and available for use. It will attempt to use our __autoload and check for the file “myobject.php”. If it is not found, it will use the next registered autoload (which could be in a separate file) and use “myobject-example1.php” and lastly check the third autoload (which again could be in a separate file) and use “myobject-example2.php”.

Wow, that is a lot of checking for class definitions in include files. But as you can see you could customize your autoload functions a lot to fit your library and not have to worry about conflicting with other libraries that might be used by a user. You might make your include files prefixed with a company name, or some other naming convention, and use your own autoload to load files specific to your library at runtime. They could be elaborate functions and do things, like verifying if the files exist, and make it easier for you to implement versioning. Like checking if one file is there and if not, use another as a fall back version.

That is all there is to it. I hope you have enjoyed this entry of the Programming Underground and if you decide to take over the world using an __autoload(), please… I want to have a nice tropical island somewhere where I could rule with an iron fist. I think that would be sooooo great! You never know, knowledge is the ultimate weapon of destruction as well as peace. Use it wisely!

Thanks again for reading. 🙂

About The Author

Martyr2 is the founder of the Coders Lexicon and author of the new ebooks "The Programmers Idea Book" and "Diagnosing the Problem" . He has been a programmer for over 20 years. He works for a hot application development company in Vancouver Canada which service some of the biggest tech companies in the world. He has won numerous awards for his mentoring in software development and contributes regularly to several communities around the web. He is an expert in numerous languages including .NET, PHP, C/C++, Java and more.