How to Implement An Autoloader in a Legacy PHP application

The first step to modernize a PHP application should be add an autoloader. After this, when we need a class file, we will not need an include or require statement to load it for us.

A Single Location For Classes

Before we implement a PSR-0 autoloader, we need to pick a directory location in the codebase to hold every class that will ever be used in the codebase. Some projects already have such a location; it may be called “includes,” “classes,” “src,” “lib,” or something similar.

Add Autoloader Code

Once we have a central directory location for our class files, we need to set up an autoloader to look in that location for classes. We can create the autoloader as a static method, an instance method, an anonymous function, or a regular global function. (Which one we use is not as important as actually doing the autoloading.) Then we will register it with spl_autoload_register() early in our bootstrap or setup code, before any classes are called.

As A Global Function

Perhaps the most straightforward way to implement our new autoloader code is as a global function. Below, we find the autoloader code to use; the function name is prefixed with fp to make sure it does not conflict with any existing function names.

                                        
                                            <?php

function fp_autoloader($class) {
   // strip off any leading namespace separator from PHP 5.3
  $class = ltrim($class, '\\');

  // the eventual file path
  $subpath = '';
  
  // is there a PHP 5.3 namespace separator?
  $pos = strrpos($class, '\\');
  if ($pos !== false) {
	// convert namespace separators to directory separators
	$ns = substr($class, 0, $pos);
	$subpath = str_replace('\\', DIRECTORY_SEPARATOR, $ns) . DIRECTORY_SEPARATOR;
	// remove the namespace portion from the final class name portion
	$class = substr($class, $pos + 1);
  }
  
  // convert underscores in the class name to directory separators
  $subpath .= str_replace('_', DIRECTORY_SEPARATOR, $class);
  
  // the path to our central class directory location
  $dir = '/path/to/app/classes';
  
  // prefix with the central directory location and suffix with .php,
  // then require it.
  $file = $dir . DIRECTORY_SEPARATOR . $subpath . '.php';
  require $file;
}

// register it with SPL
spl_autoload_register('fp_autoloader');
                                        
                                    

Composer autoloader

We need to understand how the autoloader works behind the scenes, but it's recommended to use the Composer autoloader instead of a custom one. First, you will need to add a Composer config file.:

                                        
                                            {
  "name": "masterfermin02/vicidial",
  "description": "This is model and easy to integrate vicidial admin panel",
  "keywords": ["vicidial", "PHP", "No frameworks", "admin", "panel", "dashboard"],
  "license": "MIT",
  "authors": [
    {
      "name": "Fermin Perdomo",
      "email": "[email protected]",
      "role": "Creator / Main Developer"
    }
  ],
  "require": {
    "php": "7.4.33"
  },
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    }
  },
  "autoload-dev": {
    "psr-4": {
      "Test\\": "tests/"
    }
  },
  "require-dev": {
    "phpunit/phpunit": "^9"
  },
  "scripts": {
    "test": "phpunit tests"
  }
}
                                        
                                    

Now you can run composer install:

                                        
                                            composer install
                                        
                                    

Now, in your main file, you can use the Composer autoloader.:

                                        
                                            <?php

require __DIR__ . '/vendor/autoload.php';