Detailed Explanation of PHP Automatic Loading Mechanism Example

  • 2021-10-24 19:04:07
  • OfStack

This paper illustrates the automatic loading mechanism of PHP. Share it for your reference, as follows:

In php, we use require , requre_once , include , include_once These four commands load other php files, which is no problem in a small php file. I believe every beginner will encounter such an application scenario: use an Db. php to define database connection, and directly reference this file in other files to achieve the effect of code reuse.

Let's consider such an application scenario. If we use a framework or a third-party package, there are hundreds of class files in it, and we usually don't have to load these files ourselves. At this time, we use the automatic loading mechanism of php.

Define 1 auto-load mode

In traditional applications, you usually customize __autoload() . As follows


define("DIR", "/var/www/myWeb/myClass/");
function __autoload($classname) {
  require DIR.$classname.'.class.php';
}
$book = new Book();

The above code works as follows:

1. Customize __autoload Function, which defines how the class file is loaded
2. When we have an new instance of Book, it first looks at whether this class is currently included, and if it does not exist, it will automatically call __autoload Function and pass the class name Book as an argument to this function. This is actually a dynamic loading method, and only the class files we need will be loaded.
STEP 3 Find __autoload Function, find the defined load action require DIR.$classname.'.class.php'; At this time, it will go to the DIR directory to find the Book. class. php file, and load it if it exists.
4. The definition of class Book. class. php must meet the following conditions: class name and file name 1; One file defines only one class.

The file Book. class. php is as follows


class Book {
  public function __construct() {
    echo "this is Book's construct\n";
  }
}

Register multiple load modes

For our own simple application, one loading mode may be enough, but for larger applications, the above method has obvious defects: __autoload Functions cannot be defined repeatedly, that is to say, we can only define one mode of loading files, and the final result is that our classes can only be placed in one place, which obviously does not meet the actual requirements. So php uses a function requre_once0 Instead of __autolaod .

The code is as follows:


define("MODEL_DIR", "/var/www/myWeb/myModel/");
define("CONTROLLER_DIR", "/var/www/myWeb/myController/");
//  Definition Model Class loading mode 
function loadModel($classname) {
  $filename = MODEL_DIR.$classname.'.php';
  if (file_exists($filename))
    require $filename;
}
//  Definition Controller Loading mode 
function loadController($classname) {
  $filename = CONTROLLER_DIR.$classname.'.php';
  if (file_exists($filename))
    require $filename;
}
//  Register two load functions 
spl_autoload_register("loadModel");
spl_autoload_register("loadController");
//  Automatically load class files 
$bookMode = new BookMode();
$bookController = new BookController();

In the above code, we can see:

1. You can define multiple load functions using any function name
2. In requre_once0 Registering the load function should actually be added to a data structure similar to a bidirectional queue.
3. When our new object does not exist in the current file, it will be automatically found in our load function, and it will be found according to our use requre_once0 Registration is carried out in the order.
4. It should be noted that if we define the __autoload method at this time, we must also register it, otherwise it will be ignored.

requre_once0 There are three ways to register functions:


spl_autoload_register(funName); //  Direct registration 1 Ordinary loading functions 
spl_autoload_register(obj::method); //  Registration 1 Static loading methods 
spl_autoload_regitser(array(obj, method)); //  When obj Is a class string, only static methods can be loaded. Otherwise, you can do it. 

Instances

In various php frameworks, automatic loading mechanism is also widely used. Let's look at it through a small example of laravel.

laravel helps us manage dependencies through Ioc container, so that we can happily get class instances through function parameters, but we also find that we don't have require file, so how does the container find our file address? Let's solve this problem.

Through the entry file index. php, we can find the/vendor/composer/ClassLoader. php file.

Part of the code is as follows


public static function loadClassLoader($class)
{
  if ('Composer\Autoload\ClassLoader' === $class) {
    require __DIR__ . '/ClassLoader.php';
  }
}
public static function getLoader()
{
  if (null !== self::$loader) {
    return self::$loader;
  }
  spl_autoload_register(array('obj', 'loadClassLoader'), true, true);
  //  Using registered load classes through namespaces 
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
  spl_autoload_unregister(array('obj', 'loadClassLoader'));
  if (PHP_VERSION_ID >= 50600) {
    //  This file defines the mapping of namespaces and entity files for package and user classes 
    //  And others 1 Something 
    require_once __DIR__ . '/autoload_static.php';
    //  Initialization $loader1 Some attributes. 
    //  We're concerned autoload_static.php Class mapping of files 
    //  Has been assigned a value in  $loader Adj. $classMap Attribute 
        call_user_func(\Composer\Autoload\ComposerStaticInit::getInitializer($loader));
    // ...
  }
  // ...
  $loader->register(true);
  // ...
  return $loader;
}

It calls the getLoader() Function and set the loadClassLoader Function to the load function registration queue. Then you can use namespaces self::$loader = $loader = new \Composer\Autoload\ClassLoader(); Instantiate the ClassLoader class.

Next, he loads the /autoload_static. php file, which reads roughly as follows


//  It also defines package classes and psr Adj. 1 Some standards 
public static $classMap = array (
  'App\\Common\\Collection' => __DIR__ . '/../..' . '/app/Common/Collection.php',
  'App\\Common\\MgDB' => __DIR__ . '/../..' . '/app/Common/MgDB.php',
  'App\\Common\\Redis' => __DIR__ . '/../..' . '/app/Common/Redis.php',
)

I am excited to see here, because the above Collection and Redis are the classes defined by the author!
Then there is the noun "register" that we often hear in laravel. Look at the register method of the ClassLoader class as follows:


public function register($prepend = false)
{
  spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
public function loadClass($class)
{
  if ($file = $this->findFile($class)) {
    includeFile($file);
    return true;
  }
}
public function findFile($class)
{
  // ...
  // class map lookup
  if (isset($this->classMap[$class])) {
    return $this->classMap[$class];
  }
  // ...
}

The register method above also uses the auto-load mechanism. The exact location of the corresponding class will be found directly through the findFile function and the $classMap array. That's why we don't have to load the class file ourselves. When we instantiate a class that we can't find in the code, it loads the corresponding class here.

See here, we also found that its use and what we said before are not completely 1. We register the function to find classes through folders, while laravel register the function to register a mapping array and then call it directly (the whole mapping file has more than 3,000 lines...) Why do you have to wait for the next time to read through the loading source code part and then write a blog post (originally only want to find an example of a framework, honey embarrassment)

Author's example

Two years ago, when I was in charge of the online part of an association in the school, I mainly developed WeChat. Because a new function had to be added from time to time, it was painful to write in a general way, but it was a bit overqualified to use the framework. Because the following simple method is used:


require "./basic/init.php";
define('WEB_PATH', '');
// Declare and register the auto-load function, indicating the load path and load method 
  function wechatAutoload($class_name)
  {
    $file_road = './function/'.$class_name.'.class.php';
    if(file_exists($file_road))
    {
      require_once($file_road);
    }
  }
  spl_autoload_register('wechatAutoload');
//----------------------------------------------

After initializing the configuration, we registered a load function. In the future, every new function only needs to add a file under the function folder, and the other parts are changed little or no (according to the business scenario).

Reference: PHP: spl_autoload_register-Manual

For more readers interested in PHP related content, please check the topics on this site: "Introduction to php Object-Oriented Programming", "Encyclopedia of PHP Array (Array) Operation Skills", "Introduction to PHP Basic Syntax", "Summary of PHP Operation and Operator Usage", "Summary of php String (string) Usage", "Introduction to php+mysql Database Operation Skills" and "Summary of php Common Database Operation Skills"

I hope this article is helpful to everyone's PHP programming.


Related articles: