Namespace and Automatic Loading Method of php
- 2021-12-19 06:24:36
- OfStack
Automatic loading of classes
Introduction
When we load a class in the php code, we must have a class file of include or require.
However, similar situations are encountered, such as:
require "Class1.php";
require "Class2.php";
$boy = $_GET['sex'] = 0?true:false;
if($boy)
{
$class1 = new Class1();
}else{
$class2 = new Class2();
}
If we need to determine the gender of a person, instantiate the class class1 if it is male, and instantiate the class class2 if it is female. Here's the problem: In this code, I only need to execute one instantiation object at a time, but I have to load these two class files.
php provides a solution to this problem
spl_auto_register()
This concept was introduced in php 5.1
spl_auto_register($autoload_function = null, $throw = true, $prepend = false)
The function takes three arguments
autoload_function This is the name of a function "method", which can be a string or an array (used for calling class methods). The function (method) is to include include (requeire) in the class file that requires new, so that the file will not be lost when new. In fact, it is the include and require functions that encapsulate the whole project.
$throw This parameter specifies whether spl_autoload_register () should throw an exception when autoload_function cannot be registered.
If it is true, then spl_autoload_register () will come before the auto-load into the file, and from time to time after it.
Usage
So after having this function, I wrote it like this
function load($class)
{
require "./{$class}.php";
}
spl_autoload_register('load');
if($boy)
{
$class1 = new Class1();
}else{
$class2 = new Class2();
}
The program execution process is as follows:
//Normal process
new 1 object-- > Object not found-- > Report an error//After the introduction of spl_autoload_register
new 1 object-- > Object not found-- > spl_autoload_register said to me to try-- > Load succeeded
After loading, we executed the function load, and through the splicing of class, we completed the process of loading the function
__autoload()
Auto-loading of classes was discussed earlier when we talked about spl_autoload_register. Today we talk about another kind
__autoload () is no longer recommended in php 7
The __autoload function of php is a magic function. Before this function appeared, if 100 objects were referenced in an php file, then this file needed to introduce 100 class files using include or require, which would lead to the huge php file. So there is this __autoload function.
When is the __autoload function called? When the php file uses the new keyword to instantiate an object, if the class is not defined in this php file, the __autoload function will be triggered. At this time, the php file defining the class can be introduced, and then the instantiation is successful.
(Note: The __autoload function will not be triggered if the object to be instantiated has a definition of the class found in this file.)
The difference between him and spl_autoload_registe r is that when __autoload and spl_autoload_register appear in the file at the same time, spl_autoload_register shall prevail
Namespace
We talked about automatic loading of classes earlier, and then I was thinking about it.
When we write code with the framework, every time we call other classes in another file,
We didn't write the method spl_autoload_register? So how did we achieve it?
Principle
It turns out that we php introduced the concept of namespace in 5.3 (which is why most frameworks do not support versions before 5.3). Namespace is still known to everyone: If you don't know it, you have to think about it in the corner
Namespace is simply an identity, and its main purpose is to solve the problem of naming conflicts. Just like in daily life, there are many people with the same name. How to distinguish these people? Then you need to add one extra logo. It seems good to regard the work unit as a logo, so that you don't have to worry about the embarrassment of "bumping into your name".
Namespace classification
new Chengdu \ Xu Dashuai (); // Qualified class name
new \ Chengdu \ Xu Dashuai (); // Fully qualified class name
A qualified class name and a fully qualified class name are equivalent when the current namespace is not declared. Because if no space is specified, the default is global ().
namespace United States ;
new Chengdu \ Xu Dashuai (); // United States \ Chengdu \ Xu Dashuai (actual result)
new \ Chengdu \ Xu Dashuai (); // Chengdu \ Xu Dashuai (actual result)
This example shows the difference between using qualified class names and fully qualified class names under namespaces. (Fully qualified class name = current namespace + qualified class name)
/* Import Namespace */
use Chengdu \ Xu Dashuai ;
new Xu Dashuai (); // Chengdu \ Xu Dashuai (actual result)
/* Setting Alias */
use Chengdu \ Xu Dashuai AS CEO;
new CEO(); // Chengdu \ Xu Dashuai (actual result)
/* In any case */
new \ Chengdu \ Xu Dashuai ();// Chengdu \ Xu Dashuai (actual result)
Using namespaces only prefixes class names, which are not prone to conflicts, and the system still does not import automatically.
If the file is not imported, the system fires the __autoload () or spl_autoload_register function before the "Class Not Found" error is thrown, passing in the qualified class name as an argument.
The above examples are based on the fact that you have manually introduced relevant files, otherwise the system will throw out "Class 'Chengdu Xu Dashuai' not found". Because she doesn't know where this file is. So automatic loading was introduced after namespaces were introduced
Next, we are loading our class with the namespace
A small experiment to automatically load classes using namespaces
First, we define in a new file
//School.php
namespace top;
class School
{
function __construct()
{
echo ' This is '.__CLASS__.' Implementation of the ';
}
}
This is certainly not important, what is important is that we call his function. We create an index. php file in the same directory (different files are OK, as long as you write the mapping relationship)
//index.php
spl_autoload_register(function ($class){
// From our class Find in the name, is there a corresponding path
$map = [
'top\\School'=>'./School.php'
];
$file = $map[$class];
// Check whether the corresponding file exists
if (file_exists($file))
include $file;
});
echo " Begin <br/>";
new top\School();
Results
Begin
This is the implementation of the top\ School class
We use the mapping relationship between class name and class address to realize our automatic loading. However, this also means that every time we add a file, we must update our mapping file. In a large system, the mapping relationship maintained by such arrays is undoubtedly troublesome. So is there a better way?
PSR4 Automatic Loading Specification
Children's shoes that don't know can be seen here
PSR4 Chinese Document
Specific Explanation of PSR4
The following is an excerpt from the above link, which I think has been thoroughly explained in the above two articles
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
There must be a top-level namespace in the PSR-4 specification, which means to represent a special directory (file base directory). The sub-namespace represents the 1 path (relative path) of the class file relative to the file base directory, while the class name and the file name remain 1 (pay attention to the difference between case and case).
For example, in the fully qualified class name appviewnewsIndex, if app stands for C: Baidu, then the path of this class is C: BaiduviewnewsIndex. php
Let's take parsing appviewnewsIndex as an example and write a simple Demo:
$class = 'app\view\news\Index';
/* Top-level namespace path mapping */
$vendor_map = array(
'app' => 'C:\Baidu',
);
/* The parsing class name is file path */
$vendor = substr($class, 0, strpos($class, '\\')); // Take out the top-level namespace [app]
$vendor_dir = $vendor_map[$vendor]; // File base directory [C:\Baidu]
$rel_path = dirname(substr($class, strlen($vendor))); // Relative path [/view/news]
$file_name = basename($class) . '.php'; // Filename [Index.php]
/* Path of output file */
echo $vendor_dir . $rel_path . DIRECTORY_SEPARATOR . $file_name;
From this Demo, we can see the process of converting qualified class names into paths. Now let's implement the auto-loader in a standard object-oriented way.
First we create a file Index. php, which is in the appmvcviewhome directory:
spl_auto_register($autoload_function = null, $throw = true, $prepend = false)
0
Next, we are creating a load class (no namespace is required), which is in the directory:
spl_auto_register($autoload_function = null, $throw = true, $prepend = false)
1
Finally, register autoload in the Loader class into the spl_autoload_register function:
spl_auto_register($autoload_function = null, $throw = true, $prepend = false)
2
The code in the example is actually a simplified version of the source code of ThinkPHP auto-loader, which is the key to the lazy loading of ThinkPHP 5.
Summarize