PHP Package Management and Autoloading

In PHP 5 and greater there is a magic function called __autoload (note: two underscores). __autoload allows us to load a class on the fly so to speak. It only gets called when a class can not be found, then it has a chance to load the class. If the class still can not be found, you get your regular error stating so. __autoload can be really useful if all of your classes happen to be in one directory, but what happens if you are managing a large project with many packages of classes? We will look at some different options.

Single Directory of Classes

This is the simplest solution, and the best if you have a small project. You may have situations where you would like to load the class without creating a new instance of it, so I will be creating a loadClass function in each example which __autoload will call. That way you may load a class manually. Here is what you might do if all of your classes are in one directory:

function __autoload($className) {

function loadClass($className) {
    include_once('classes/' . $className . '.php');

Pretty Simple.

Packages of Classes

Now how about package management, with many directories of classes? A few developers have named their classes with the package names in the class name. For example, util_Parser would be the Parser class in the util directory (in your base classes directory), and util_html_HTMLParser would be the HTML parser class in the util.html package. Here is an example of how that would work:

function __autoload($className) {

function loadClass($className) {
    include_once('classes/' . str_replace('_', '/', $className) . '.php');

Simple like the first method, but we get packages now. However, we have to actually name our classes with the package names in front of it. We start to get very long names for some of our classes. If we extended the Parser class we might have util_html_HTMLParser and util_xml_XMLParser or perhaps even deeper packages. We also find refactoring difficult because if a class must move to another package, we must go through all our code and rename the class everywhere we use it.

Package Management Using import

There is another way, although not as simple, which allows packages as deep as you would like, and requires minimal work when refactoring. This is the import way of doing things. import is a function which keeps track of what classes you might use in a certain script/class and then uses __autoload to look up the location of the class. Here’s how it works.

  • You import the class or package using the import function like this, import('util.html.HTMLParser');, at the top of your script
  • import stores the name of the class, ‘HTMLParser’, and the path to the class, ‘util/html/HTMLParser.php’, in a global associative array called imports
  • When the class is utilized, __autoload will do a lookup in the imports array for the class and load it in.

Here is how the code looks. It is a bit more complicated, but very nice to use for a larger system:

function __autoload($className) {

function loadClass($className) {
    global $imports;
    if (isset($imports[$className])) {

$imports = array();
function import($import) {
    global $imports;

    // seperate import into a package and a class
    $lastDot = strrpos($import, '.');
    $class = $lastDot ? substr($import, $lastDot + 1) : $import;
    $package = substr($import, 0, $lastDot);

    // if this import has already happened, return true
    if (isset($imports[$class]) || isset($imports[$package.'.*'])) return true;

    // create a folder path out of the package name
    $folder = '' . ($package ? str_replace('.', '/', $package) : '');
    $file = "$folder/$class.php";

    // make sure the folder exists
    if (!file_exists($folder)) {
        $back = debug_backtrace();
        return trigger_error("There is no such package <strong>'$package'</strong> -- Checked folder <strong>'$folder'</strong><br />
            Imported from <strong>'{$back[0]['file']}'</strong> on line <strong>'{$back[0]['line']}'</strong><br />", E_USER_WARNING);
    } elseif ($class != '*' && !file_exists($file)) {
        $back = debug_backtrace();
        return trigger_error("There is no such Class <strong>'$import'</strong> -- Checked for file <strong>'$file'</strong><br />
            Imported from <strong>'{$back[0]['file']}'</strong> on line <strong>'{$back[0]['line']}'</strong><br />", E_USER_WARNING);

    if ($class != '*') {
        // add the class and it's file location to the imports array
        $imports[$class] = $file;
    } else {
        // add all the classes from this package and their file location to the imports array
        // first log the fact that this whole package was alread imported
        $imports["$package.*"] = 1;
        $dir = opendir($folder);
        while (($file = readdir($dir)) !== false) {
            if (strrpos($file, '.php')) {
                $class = str_replace('.php', '', $file);
                // put it in the import array!
                $imports[$class] = "$folder/$file";

There you have it. A powerful way to manage your packages and load only classes which are needed for use. Also, a feature of this method of autoloading classes is that you can use an asterisk, *, to import all the classes in a package. And it only loads the classes needed because of __autoload.

Finally, this is how you would use the import method in your scripts:


// here would be all of your important code
// not worrying about including files hwen you need them
// because you've already set it up to include them
// automatically when you use them, and only
// _if_ you use them
$p = new HTMLParser();
$t = new ArrasTemplate();
// etc.

28 Responses to “PHP Package Management and Autoloading”

  1. Neill Jones Says:

    Thanks for this – solved my problem almost exactly. I wasn’t interested in packages, just stopping loads of classes being loaded until they were needed and wanted so this was pretty much what I wanted.

    Thanks again

  2. Vance Dubberly Says:

    It should prolly be noted, since at some point someone’s going to use this and watch their app explode ( especially since alot of people are attempting to write real programs with PHP these days), that this is package management for the sake file organization but it doesn’t provide the name space protection of true packages. So if you have two classes in two packages called… oh lets say, “database.Record” and “” you’re SOL. Someday PHP will grow up, but until then this is a nice hack for keeping things organized.

  3. Jacob Wright Says:

    Very true Vance. The first method is safer if you name the classes package_subpackage_Class. Of course, if you’re using existing libraries and you’ve got a database Record class and a music Record class your SOL whether you use this way of importing or not.

  4. Howie Says:

    Interesting. Coming from a Java background, and now learning to use PHP5, this solution suits me.

    One thought re name collision.. why not name the php file com.mycompany.mypackage.myclass.php ? i.e use the package name in the filename, rather than the directory structure? This way, all clases live in one folder, but have a unique name

    Just a thought

  5. Jacob Wright Says:

    Having all the classes in one folder would drive me crazy. But you could certainly modify the code to do that. :) Wouldn’t be difficult.

  6. ujjwal soni Says:

    Its really intresting. I am a J2EE developer, really liked this article.


    Ujjwal B Soni

  7. Neill Jones Says:

    I’ve added you to a “Thanks to” page on our website. It’s proved very useful to us.

    The link is

    Thanks again.

  8. Adil Says:


    it’s interesting, many thanks.

    i need further feature if possible; suppose test1.php is in the folowing directory myProject/test/views/test1.php; and my class Class1.php is in myProject/classes/Class1.php, so when using your function in test1.php like this:
    import(classes.Class1.php) i got an error saying no folder… the error is clear because test1.php looks for, from its current directory (views), the directory classes and it doesn’t find it. how can i overcome this problem?


  9. Rajeev Jha Says:

    PHP 5.3 is introducing name space support. More details are here :-
    and here
    and here

    I believe doing an import without name spaces support will not work for large code bases. Till the time sticking to X_Y_Z pattern is safer.

  10. Razaul Says:

    You have done really good job, thanx, its very useful for my current project, thanx once again, can you tell me that the function import is working actually include() all class file?

  11. Jacob Wright Says:

    if you do an import(‘mypackage.*’); it will “register” all the filenames so that when a class is referenced it can know where to include() the PHP from. include() only happens when actually using the class you need. However, using “*” in the import will scan the directory for the filenames, so use sparingly.

  12. Benux Says:

    thanks, great job, this really gave me some good ideas for my projects, its very interesting.

    for that thing of “*” you could use some regular expressions instead of strrpos to make it more restrictive with the uppercase convention and the “.php” ending extension, something like this:

    if (preg_match(‘/^[A-Z](?.*).php$/’, $file,$class)) {
    $imports[$class[‘name’]] = “$folder/$file”;

  13. Benux Says:

    well i repeat the code in another for cause the system erase the name tag after the “?” haha, hopes this comes useful

    if (preg_match(’/^[A-Z](.*).php$/’, $file,$class)) {
    $imports[$class[1]] = “$folder/$file”;

    thanks again.

  14. Jon Dean Says:

    Thanks, this is very cool. Is it available for use via a public license? Without one explicitly given it’s technically not legal to reuse since you can claim copyright at any time (an implicit copyright.)

    A few example licenses:

    MIT License allows for most use but you must include the copyright notice every time:

    Public domain has no restrictions at all:

    Anyway, thanks a lot!

  15. Jacob Wright Says:

    This is under the creative commons Attribution license (

  16. anisa Says:

    how i can get the php package dawnlode

  17. Jacob Wright Says:

    anisa: copy/paste into a file.

  18. Sven Neumann Says:

    My own derivation from your code:

    The following is placed in classes/ and included via require_once(‘classes/’);

    It will turn this
    new TagStorageData()

    new ITagStorageData()

    define(‘CLASS_EXT’, ‘.class.php’);
    define(‘INTERFACE_EXT’, ‘.interface.php’);

    function __autoload ($className) {

    function loadClass ($className) {
    $classesRootFolder = dirname(__FILE__);
    $classFileExtension = ”;
    if(preg_match(‘/^I[A-Z]/’, $className)) { // Interface
    $classFileExtension = INTERFACE_EXT;
    $className = preg_replace(‘/^I([A-Z])/’, ‘$1’, $className);
    } else { // Class
    $classFileExtension = CLASS_EXT;
    $parts = preg_split(‘/(?<!^)(?=[A-Z])/', $className);
    $classFileName = strtolower(implode('_', $parts).$classFileExtension);
    array_pop($parts); // Drop final element
    $classFileName = strtolower(implode('/', $parts)).'/'.$classFileName;
    echo "Auto-loading Class: $className in $classFileName\n";
    $classFileName = $classesRootFolder.'/'.$classFileName;

  19. Andrey Skorikov Says:

    Jacob’s solution can be misleading in two ways.

    Firstly, it creates the illusion that there are some kind of packages in PHP, which is not the case, so the problem of name collisions remains. Howie have already pointed that out.

    Secondly, declaring “imported” classes at the top of the file does not imply that those are the only dependencies required by the script. Some classes might already have loaded other classes too. It’s kind of a hint, though.

    Personally, since there is no notion of a package in PHP (though in PHP 5.3 namespaces are introduced), i find there is no need to specify the exact location of the “imported class”. There is no way for explicitly declaring the dependencies either. So, basically the only things i want to (and can) achieve are:

    1. Get rid of the require or include statements
    2. Organize files in some kind of hierarchy

    The idea is just to build the include_path to contain all the subdirectories. That way i can easily move files around without worrying about any class loading issues.


    function init() {
    $path = implode(dirs(“classes”), PATH_SEPARATOR);

    function dirs($path) {
    $dirs = array($path);
    $contents = scandir($path);
    foreach ($contents as $filename) {
    if (ignored($filename)) {
    $item = “{$path}/{$filename}”;
    if (is_dir($item)) {
    $dirs = array_merge($dirs, dirs($item));
    return $dirs;

    function ignored($filename) {
    return preg_match(“/^\./”, $filename);

    function __autoload($class) {

  20. ryan teixeira Says:

    I prefer Andrey’s solution. I see no need to explicitly list directories. Manipulate the include_path to include all the directories where files would be located.

    Consider whether a solution like this is really needed before implementing it.

    Lastly, I think it would be a mistake to try to make PHP look like Java.

  21. Raymond Says:

    Cool, I wasn’t aware of this function

  22. varsha(Student) Says:

    here u haven’t defined how to actually define package.

    as in java u can define package as..
    package packageName;

    please help me.

  23. Jacob Wright Says:

    varsha: The package is the folder path. There is no package declaration.

    ryan: the goal isn’t to look like Java, but to make loading php files with classes easier. But it isn’t for everyone. And now PHP has namespaces!

  24. Andreas Feldmann Says:


    pretty cool way to simulate packages in PHP. As for me I learned PHP first and then stuff like Java, C# Scala etc. And always missed the packages in PHP(and the namespaces are not very usefull for this). So I really like your solution, but for larger project it wouldn’t be effective to write the code in every class.

  25. st.m Says:

    Thanks for this great solution. Been missing this in PHP.

    And Andreas, there’s no need to include the code in every class, as long as it’s included once in the documents calling the classes in the library (like initializing the library in a main document).

  26. Bayu Idham Fathurachman Says:

    thanks , this is awesome :)

  27. Diogo Silvé » Múltiplos classloaders e a função spl_autoload_register do PHP 5 Says:

    […] blog do Jacob Wright, tem um artigo super legal desenvolvendo uma função mais elaborada de classloader, recomendo a leitura. Tags: autoload, […]

  28. Guest Says:

    Readers of this article will probably be interested in this article