In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly explains "the overview and implementation of PHP autoload mechanism". The content of the explanation is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "the overview and implementation of PHP autoload mechanism".
1. Overview of autoload mechanism
When developing a system using PHP's OO pattern, it is customary to store the implementation of each class in a separate file, which makes it easy to reuse the class and convenient for maintenance in the future. This is also one of the basic ideas of OO design. Before PHP5, if you needed to use a class, you just needed to include it directly using include/require. Here is a practical example:
/ * Person.class.php * / / * no_autoload.php * /
In this example, the no-autoload.php file needs to use the Person class, which uses require_once to include it, and then you can instantiate an object directly using the Person class.
However, as the size of the project continues to expand, using this approach will bring some implicit problems: if a PHP file needs to use many other classes, then it will require a lot of require/include statements, which may result in omissions or inclusion of unnecessary class files. If a large number of files need to use other classes, it must be a nightmare to make sure that each file contains the correct class file.
PHP5 provides a solution to this problem, which is the autoload mechanism of classes. The autoload mechanism makes it possible for PHP programs to automatically include class files when they use classes, rather than include all class files in the first place. This mechanism is also called lazy loading.
Here is an example of using the autoload mechanism to load the Person class:
/ * autoload.php * /
Usually when PHP5 uses a class, if it finds that the class is not loaded, it automatically runs the _ _ autoload () function, in which we can load the class we need to use. In our simple example, we directly add the class name to the extension ".class.php" to form the class file name, and then use require_once to load it. From this example, we can see that autoload has to do at least three things, the first thing is to determine the class file name based on the class name, the second thing is to determine the disk path of the class file (in our simplest case, the class is in the same folder as the PHP program file that called them), and the third thing is to load the class from the disk file into the system. The third step is the easiest, just use include/require. To realize the function of the first step and the second step, we must agree on the mapping method between the class name and the disk file at the time of development. only in this way can we find the corresponding disk file according to the class name.
Therefore, when there are a large number of class files to include, we just need to determine the corresponding rules, and then in the _ _ autoload () function, we can achieve the effect of lazy loading by matching the class name with the actual disk file. From this we can also see that the most important thing in the implementation of the _ _ autoload () function is the implementation of the mapping rules between the class name and the actual disk file.
But now the problem is, if in the implementation of a system, if you need to use many other class libraries, these class libraries may be written by different developers, and their class names are different from the mapping rules of the actual disk files. At this time, if you want to achieve the automatic loading of class library files, you must implement all the mapping rules in the _ _ autoload () function, so the _ _ autoload () function may be very complex or even impossible to implement. Finally, the _ _ autoload () function may be very bloated, and even if it can be implemented, it will have a great negative impact on future maintenance and system efficiency. In this case, is there no simpler and clearer solution? The answer is, of course: NO! Before looking at further solutions, let's take a look at how the autoload mechanism in PHP is implemented.
2. Implementation of autoload mechanism of PHP
We know that the execution of PHP files is divided into two separate processes. The first step is to compile the PHP file into a bytecode sequence commonly called OPCODE (actually into a byte array called zend_op_array), and the second step is for a virtual machine to execute these OPCODE. All the behaviors of PHP are implemented by these OPCODE. Therefore, in order to study the implementation mechanism of autoload in PHP, we compile the autoload.php file into opcode, and then use these OPCODE to study what PHP does in the process:
/ * the compiled OPCODE list of autoload.php is the result of using the OPDUMP tool * developed by the author. You can download the software from the website http://www.phpinternals.com/. * / 1:
In line 10 of autoload.php, we need to instantiate an object for the class Person. Therefore, the autoload mechanism must be reflected in the compiled opcode of this line. We know from the OPCODE generated in line 10 above that when instantiating the object Person, the FETCH_CLASS instruction is executed first. Let's start our journey of exploration from PHP's processing of FETCH_CLASS instructions.
By looking at the source code of PHP (I am using the PHP 5.3alpha2 version), you can find the following call sequence:
ZEND_VM_HANDLER (109, ZEND_FETCH_CLASS, …) (zend_vm_def.h 1864 lines) = > zend_fetch_class (zend_execute_API.c 1434 lines) = > zend_lookup_class_ex (zend_execute_API.c 1434 lines) = > zend_call_function (& fcall_info, & fcall_cache) (zend_execute_API.c 1040 lines)
Before the last step of the call, let's take a look at the key parameters of the call:
/ * set the value of the autoload_function variable to "_ _ autoload" * / fcall_info.function_name = & autoload_function; / / Ooops, and finally found "_ _ autoload". Fcall_cache.function_handler = EG (autoload_func); / / autoload_func!
Zend_call_function is one of the most important functions in Zend Engine, and its main function is to execute user-defined functions in PHP programs or library functions of PHP itself. Zend_call_function has two important pointer parameters, fcall_info and fcall_cache, which point to two important structures, one is zend_fcall_info and the other is zend_fcall_info_cache. The main workflow of zend_call_function is as follows: if the fcall_cache.function_handler pointer is NULL, try to find a function named fcall_info.function_name, if it exists, execute it; if fcall_cache.function_handler is not NULL, execute the function pointed to by fcall_cache.function_handler directly.
Now we know that when PHP instantiates an object (in fact, when implementing an interface, using class constants or static variables in a class, and calling static methods in a class), it first looks in the system to see if the class (or interface) exists, and if not, tries to use the autoload mechanism to load the class. The main implementation process of autoload mechanism is as follows:
Check whether the executor global variable function pointer autoload_func is NULL.
If autoload_func==NULL, find out if the _ _ autoload () function is defined in the system, if not, report an error and exit.
If the _ _ autoload () function is defined, execute _ _ autoload () to attempt to load the class and return the load result.
If autoload_func is not NULL, the function pointed to by the autoload_func pointer is executed directly to load the class. Note that the _ _ autoload () function is not checked for definition at this time.
The truth finally comes out that PHP provides two ways to implement the automount mechanism, one of which, as we mentioned earlier, is to use the user-defined _ autoload () function, which is usually implemented in the PHP source program; the other is to design a function to point the autoload_func pointer to it, which is usually implemented in the PHP extension using the C language. If you implement both the _ _ autoload () function and autoload_func (pointing autoload_func to a PHP function), only the autoload_func function is executed.
3. Implementation of SPL autoload mechanism
SPL is the abbreviation of Standard PHP Library (standard PHP library). It is an extension library introduced by PHP5. Its main functions include the implementation of autoload mechanism and various Iterator interfaces or classes. The SPL autoload mechanism is implemented by pointing the function pointer autoload_func to the function with auto-loading function implemented by itself. SPL has two different functions, spl_autoload and spl_autoload_call, which implement different automatic loading mechanisms by pointing autoload_func to these two different function addresses.
Spl_autoload is the default auto-loading function implemented by SPL, and its function is relatively simple. It can receive two parameters, the first parameter is $class_name, indicating the class name, the second parameter $file_extensions is optional, indicating the class file extension, you can specify multiple extensions in $file_extensions, separated by semicolons; if not specified, it will use the default extension .inc or .php. Spl_autoload first lowercase $class_name, then searches all include path for $class_name.inc or $class_name.php files (if the $file_extensions parameter is not specified), and if found, loads the class file. You can manually use spl_autoload ("Person", ".class.php") to load the Person class. In fact, it is similar to require/include, except that it can specify multiple extensions.
How do you make spl_autoload work automatically, that is, pointing autoload_func to spl_autoload? The answer is to use the spl_autoload_register function. The first time you call spl_autoload_register () in a PHP script, you can point the autoload_func to spl_autoload without any arguments.
From the above description, we know that the function of spl_autoload is relatively simple, and it is implemented in the SPL extension, we can not expand its function. What if you want to implement your own more flexible automatic loading mechanism? At this point, the spl_autoload_call function makes its debut.
Let's first take a look at the wonder of the implementation of spl_autoload_call. Inside the SPL module, there is a global variable autoload_functions, which is essentially a HashTable, but we can simply think of it as a linked list. Each element in the linked list is a function pointer pointing to a function with the function of automatically loading classes. The implementation of spl_autoload_call itself is very simple, simply execute each function in the linked list sequentially, determine whether the required class has been loaded once after the execution of each function is completed, and return directly if the load is successful, and no longer continue to execute other functions in the linked list. If the class is not loaded after all the functions in the linked list have been executed, spl_autoload_call exits directly and does not report the error to the user. Therefore, using the autoload mechanism, there is no guarantee that the class will automatically load correctly, the key depends on how your autoload function is implemented.
So who maintains the automatically loaded function list autoload_functions? This is the spl_autoload_register function mentioned earlier. It registers user-defined autoloading functions with the linked list and points the autoload_func function pointer to the spl_autoload_call function (note that there is one exception, which is left for you to think about). We can also remove registered functions from the autoload_functions linked list through the spl_autoload_unregister function.
As mentioned in the previous section, the _ _ autoload () function is not automatically executed when the autoload_func pointer is not null. Now that autoload_func has pointed to spl_autoload_call, what if we still want the _ _ autoload () function to work? Of course, use the spl_autoload_register (_ _ autoload) call to register it in the autoload_functions linked list.
Now back to the problem at the end of the first section, we have a solution: each class library has a different naming mechanism to implement its own autoload function, and then use spl_autoload_register to register it in the SPL autoload function queue. So we don't have to maintain a very complex _ _ autoload function.
4. Autoload efficiency problems and countermeasures
When using the autoload mechanism, many people's first reaction is that using autoload will reduce the efficiency of the system, and some people even propose not to use autoload for the sake of efficiency. After we understand the principle of the autoload implementation, we know that the autoload mechanism itself is not the reason for affecting the efficiency of the system, and it may even improve the efficiency of the system, because it does not load unwanted classes into the system.
So why do many people have the impression that using autoload will reduce the efficiency of the system? In fact, affecting the efficiency of the autoload mechanism itself is precisely the automatic loading function designed by the user. If it cannot efficiently match the class name with the actual disk file (note, here it refers to the actual disk file, not just the file name), the system will have to make a judgment on the existence of a large number of files (need to be found in the path contained in each include path), and to determine whether there is a file that needs to do disk IDUBO operation. It is well known that the efficiency of disk IDUBO operation is very low. Therefore, this is the main culprit that makes the efficiency of the autoload mechanism inefficient!
Therefore, when we design the system, we need to define a clear mechanism to map the class name to the actual disk file. The simpler and clearer this rule is, the more efficient the autoload mechanism will be.
Conclusion: the autoload mechanism is not naturally inefficient. Only the abuse of autoload and the poorly designed autoloading function will lead to the decrease of its efficiency.
Thank you for your reading, the above is the content of "Overview and implementation of PHP autoload mechanism". After the study of this article, I believe you have a deeper understanding of the overview and implementation of PHP autoload mechanism, and the specific use needs to be verified by practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.