Laravel source parsing: PHP Automatic loading function principle analysis

Source: Internet
Author: User
Tags autoload spl naming convention php class

Objective

This article is a summary of the PHP auto-load function, which includes PHP's automatic loading function, PHP namespace, PHP PSR0 and PSR4 standards, and so on.

First, PHP automatic loading function of the origin of PHP automatic loading

In the process of PHP development, if you want to introduce a class from the outside, you will typically use the include and require methods to include the file that defines the class. This is not a big problem when it comes to small-scale development. However, in large-scale development projects, the use of this approach poses some hidden problems: If a PHP file needs to use many other classes, then a lot of require/include statements are required, which can cause omissions or unnecessary class files. If a large number of files require the use of other classes, it is certainly a nightmare to ensure that each file contains the correct class file, and the cost of require_once is great.

PHP5 provides a solution to this problem, which is the automatic loading (autoload) mechanism of classes. The autoload mechanism makes it possible for PHP programs to automatically include class files when using classes, rather than having all the class files included in the first place, which is also known as lazy loading.

Summing up, the automatic loading feature brings several advantages:

  1. No include or require before using the class

  2. The use of the class will only be require/include files, the implementation of the lazy loading, to avoid the require/include redundant files.

  3. The separation of logical and entity files is realized without considering the actual disk address of the introduced class.

??
If you want to know more about the features of automatic loading, you can view the material:
PHP class Auto-loading mechanism
Implementation of PHP's autoload mechanism

PHP Auto-load function __autoload ()

Usually PHP5 when using a class, if it is found that the class does not load, it will automatically run the _autoload () function, which we customize in the program, in which we can load the class that needs to be used. Here's a simple example:

function __autoload ($classname) {    require_once ($classname. "class.php"); }

In our simple example, we directly add the class name with the extension ". class.php" to make the class file name, and then use require_once to load it. From this example, we can see that autoload must do at least three things:

  1. Determine the class file name based on the class name;

  2. Determine the disk path where the class file resides (in our case, the simplest case, the class is in the same folder as the PHP program file that calls them);

  3. Loads the class from the disk file into the system.

?
The third step is the simplest, only need to use Include/require. To implement the first step, the second step of the function, you must contract the class name and disk file mapping method at development time, so that we can find its corresponding disk file according to the class name.

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, the class name and the actual disk file corresponding to the effect of lazy loading can be achieved. From here we can also see that the most important implementation of the _autoload () function is the implementation of the class name and the actual disk file mapping rules.

Problems with the __autoload () function

If in a system implementation, if you need to use many other class libraries, these class libraries may be written by different developers, whose class names differ from the actual disk file mapping rules. If you want to implement the automatic loading of a class library file, you must implement all the mapping rules in the __autoload () function, so that the AutoLoad () function can be very complex or even impossible to implement. In the end, the AutoLoad () function can be bloated, and even if it can be achieved, it will have a significant negative impact on future maintenance and system efficiency.

So where does the problem arise? The problem occurs in _autoload () is that the global function can only be defined once, not flexible enough, so all the class name and file name corresponding to the logical rules are implemented in a function, resulting in the function of the bloated. So how to solve this problem? The answer is to use a _autoload call stack, different mapping relationships to different _autoload functions, and then unified Registration Unified management, this is PHP5 introduced SPL autoload.

SPL Autoload

SPL is the abbreviation for the Standard PHP library (PHP libraries). It is an extension library introduced by PHP5, whose main functions include the implementation of the AutoLoad mechanism and the inclusion of various Iterator interfaces or classes. SPL Autoload specifically has several functions:

  1. Spl_autoload_register: Registering the __autoload () function

  2. Spl_autoload_unregister: Unregister a registered function

  3. Spl_autoload_functions: Returns all registered functions

  4. Spl_autoload_call: Try all registered functions to load the class

  5. Spl_autoload: Default implementation of __autoload ()

  6. Spl_autoload_extionsions: Registers and returns the default file name extension used by the Spl_autoload function.

??
The detailed usage of these functions can be seen in PHP spl_autoload

Simply put, Spl_autoload is SPL's own definition __autoload () function, the function is very simple, is to register the directory (set by Set_include_path) to find the same name as the $classname. php/.inc file. Of course, you can also specify a specific type of file by registering the extension (spl_autoload_extionsions).

and Spl_autoload_register () is the autoload call stack we mentioned above, we can register many of our own _autoload () functions with this function, and when PHP cannot find the class name, PHP calls the stack. One to call the custom _autoload () function to implement the auto-load function. If we do not enter any arguments to this function, then the Spl_autoload () function will be registered.

Well, the bottom of PHP automatic loading is these, the registration mechanism is very flexible, but what is missing? As we have said above, the key to automatic loading is the class name and file mapping, this mapping relationship different frameworks have different methods, very flexible, but too flexible will appear messy, PHP has a specific mapping relationship specification, which is the PSR standard PSR0 and PSR4.

But before we talk about PSR0 and PSR4, we also need to know about PHP's namespace, because these two standards are not intended to be a mapping between a class name and a directory file, but rather a namespace-to-file mapping. Why is that? In my understanding, the normative object-oriented PHP idea, the namespace to some extent the name of the class alias, then why to introduce the namespace, the advantages of the namespace is what?

Second, namespace namespace

To understand namespaces, first look at the introduction of namespaces in official documents:

What is a namespace? In a broad sense, namespaces are a way of encapsulating things. This abstract concept can be seen in many places. For example, in an operating system, a directory is used to group related files, and for files in a directory, it plays the role of a namespace. For example, file Foo.txt can exist in both directory/home/greg and/home/other, but there cannot be two foo.txt files in the same directory. In addition, when accessing the Foo.txt file outside of directory/home/greg, we must place the directory name and directory delimiter before the file name to get/home/greg/foo.txt. The application of this principle to the field of programming is the concept of namespaces.
In PHP, namespaces are used to solve two types of problems encountered when writing a class library or application to create reusable code such as classes or functions:
1 user-written code conflicts with the name of a class/function/constant or third-party class/function/constant within PHP
2 The name of a very long identifier name (usually defined to alleviate the first type of problem), to make the source code more readable.
The PHP namespace provides a way to group related classes, functions, and constants together.

??
In short, PHP is not allowed in the program in the existence of two names of the same class or function or variable name, then some people are very confused, it can not afford the same name? In fact, many large programs rely on a lot of third-party libraries, name conflicts or something not too common, this is the official website of the first question. So how do we solve this problem? In the absence of namespaces, poor programmers can only give the class name A_b_c_d_e_f, where a/b/c/d/e/f generally have its specific meaning, so that generally will not conflict, but such a long class name to write up tired, read more uncomfortable. So PHP5 introduced the namespace, the class name is the class name, the namespace is a namespace, the program is written/read directly with the class name, run up the machine look at the namespace, this solves the problem.

In addition, namespaces provide a way to group related classes, functions, and constants together. This is also a great use of object-oriented language namespaces, where classes, variables, and functions needed for a particular purpose are written into a namespace for encapsulation.

Solve the problem of the class name, we can finally return to the PSR standard, then PSR0 and PSR4 is how to standardize the mapping between the file and the namespace? The answer is: The naming of namespaces (the amount, a bit around), the location of the class file directory, and the mappings between the two are limited, which is the core of the standard. More complete description of modern PHP new feature series (i)--namespaces

Iii. Standard of PSR

Before talking about PSR0 and PSR4, let's introduce the PSR standard. The inventor and specification of the PSR standard is: Php-fig, its website is: www.php-fig.org. It was this alliance that invented and created the PSR norm. FIG is the abbreviation of the Framework Interoperability Group (framework Interoperability Group), which was founded in 2009 by several developers of open source frameworks, and since then, many other members have been selected, although not "official" organizations, but also represent a small chunk of the community. The purpose of the organization is: to the minimum limit, to unify the coding specifications of the various projects, to avoid the style of self-development hindered the development of the programmer's trouble, so we invented and summed up the PSR,PSR is proposing a standards Recommendation (the standard recommendation) is abbreviated.

Specific and detailed specifications can be viewed
The PSR specification in PHP

PSR0 Standard

PRS-0 specification is their 1th set of specifications, mainly developed some automatic loading standards (autoloading standard) PSR-0 mandatory requirements several:

1. A fully qualified namespace and class must conform to this structure: "< Vendor name> (< namespace>) *< class name>"
2. Each namespace must have a top-level namespace ("Vendor name" provider name)
3, each namespace can have multiple sub-namespace
4. When loading from the file system, each namespace delimiter (/) is converted to Directory_separator (operating system path delimiter)
5. In the class name, each underscore (_) symbol is converted to Directory_separator (operating system path delimiter). In namespace, the underscore _ symbol has no (special) meaning.
6, when loaded from the file system, the qualified namespace and class must be the end of. PHP
7, Verdor Name,namespaces,class name can be a combination of uppercase and lowercase letters (case sensitive)

??
The rules may be a bit dizzy, let's start from the beginning.
??
We first look at the PSR0 standard, the 1th, 2, 3, 7 of the name of the namespace has been limited, 4th, 5 on the namespace and file directory mapping relationship has been limited, 6th is the file suffix name.
??
As we said earlier, how does the PSR standard regulate the mapping between namespaces and the directory in which they reside? is by restricting the name of the namespace, the location of the directory where it resides, and the mappings between the two.
??
So we may have to ask, where is the location of the directory where the files are located? In fact, the answer is:
??

Restrict namespace name + Limit namespace name to file directory mapping = Restrict file directory

??
Well, let's think about it, for a specific program, if it wants to support the PSR0 standard, what adjustments does it need to make?

  1. First, the program must define a mapping function that conforms to the PSR0 standard 4th and 5, and then register the function in Spl_register ().

  2. Second, when defining a new namespace, the name of the namespace and the directory location where the file resides must conform to 1th, 2, 3, and 7.

??
Generally for code maintenance convenience, we will only define a single namespace in a file.
??
Well, we have the name of the namespace that conforms to the PSR0, can obtain the file directory address which conforms to the PSR0 standard through the mapping relation which conforms to the PSR0 standard, if we follow the PSR0 standard to store the file correctly, we can successfully require the file, we can use the namespace, Isn't it amazing?
??
Next, let's see in detail what the PSR0 standard is all about.
??
We use the third-party library in Laravel Symfony one of the namespaces/symfony/core/request, for example, to speak about the PSR0 standard above.
??

  1. A fully qualified namespace and class must conform to this structure: "< Vendor name> (< namespace>) *< class name>"

The/symfony shown above is Vendor name, which is the name of the third-party library,/core is the Namespace name, and is generally the property information of our namespace (for example, request is the core function of Symfony); and the last request is me. The name of the namespace, the standard specification is to let people see the source of the namespace, the function is very clear, conducive to the maintenance of code.
??

2. Each namespace must have a top-level namespace ("Vendor name" provider name)

This means that each namespace has a top-level namespace similar to/symfony, why should there be such a rule? Because the PSR0 standard only takes care of the mapping after the top-level namespace, which is the/symfony/core/request part, about which directory the/symfony should be associated with, which is defined by the user or the framework itself. The so-called top-level namespace, which is the namespace of the custom mapping relationship, is typically the name of the provider (the name of the third-party library). In other words, top-level namespaces are the basis for automatic loading. Why does the standard have to be set so? The reason is simple, if a namespace is/symfony/core/transport/request, and there is a namespace/symfony/core/transport/request1, if there is no top-level namespace, We have to write two paths and these two namespaces correspond to each other, if there are Request2, Request3. With the top-level namespace/symfony, we just need a directory to correspond, the rest of the use of the PSR standard to parse the line.
??

3. Each namespace can have multiple sub-namespace

This is very simple, Request can be defined as/symfony/core/request, can also be defined as/symfony/core/transport/request,/core this namespace can have a lot of sub-namespaces, How many levels of namespaces are defined by themselves.

??

4. When loading from the file system, each namespace delimiter (/) is converted to Directory_separator (operating system path delimiter)

Now we have finally come to the mapping specification. The/Sign of the namespace is converted to a path delimiter, which means that the/symfony/core/request namespace is converted to a directory structure such as symfonycorerequest.
??

5. In the class name, each underscore _ symbol is converted to Directoryseparator (operating system path delimiter). In namespace, the underscore symbol has no (special) meaning.

This means that if our namespace is/symfony/core/request_a, then we should map it to a directory such as Symfonycorerequesta. Why is there such a rule? This is because PHP5 did not have a namespace before, the programmer can only symfony_core_request_a the name as such, PSR0 this rule is to be compatible with this situation.
The remaining two are simply not to be said.
??
With this namespace naming convention and mapping standard, we can infer where we should put the file where the namespace resides. Still take symfony/core/request as an example, its directory is/path/to/project/vendor/symfony/core/request.php, where/path/to/project is the location of your project on disk,/ Path/to/project/vendor is the directory where all third party libraries are used for the project. /path/to/project/vendor/symfony is the directory that has a corresponding relationship to the top-level namespace/symfony, and the file directory below is established according to the PSR0 standard:

/symfony/core/request =/symfony/core/request.php

Everything is perfect, isn't it? No, there are some flaws:

  1. Should we still be compatible with no namespaces?

  2. According to the PSR0 standard, the namespace/a/b/c/d/e/f necessarily corresponds to a directory structure/a/b/c/d/e/f, is this directory structure level too deep?

PSR4 Standard

At the end of 2013, a new 5th standard--psr-4 was introduced.

The PSR-4 specification describes how to specify a file path to automatically load the class definition, while standardizing the location of the automatically loaded file. This at first glance and PSR-0 repeat, in fact, there is indeed a duplication of functionality. The difference is that the PSR-4 specification is clean, removing the content that is compatible with the previous version of PHP 5.3, with a bit of PSR-0 upgrade feel. Of course, PSR-4 is not to completely replace the PSR-0, but in the necessary time to add psr-0--of course, if you want to, PSR-4 can also replace PSR-0. PSR-4 can be used in conjunction with other automatic loading mechanisms, including PSR-0.
??
The difference between the PSR4 standard and the PSR0 standard:

  1. The use of underscores in the class name does not have any special meaning.

  2. The mapping method of the namespace and the file directory has been adjusted.

For the second item we explain in detail (the principle of composer automatic loading):
If we have a namespace: Foo/class,foo is the top-level namespace, and there is a user-defined mapping to the directory:

"foo/" = "src/"

According to the PSR0 standard, the mapped file directory is: src/foo/class.php, but according to PSR4 Standard, the mapped file directory will be: src/class.php, why do you want to change it? The reason is that the namespace is too long to cause the directory hierarchy to be too deep, making the mapping between namespaces and file directories more flexible.

One more example, the source psr-4--the freshly baked PHP specification:
PSR-0 style

    vendor/    vendor_name/        package_name/            src/                vendor_name/                    package_name/                        classname.php       # Vendor_name\package_name\classname            tests/                vendor_name/                    package_name/                        classnametest.php   # Vendor_name\package_name\classname

?? PSR-4 style

    vendor/    vendor_name/        package_name/            src/                classname.php       # Vendor_name\package_name\classname            tests/                classnametest.php   # vendor_name\package_name\classnametest    vendor/    vendor_name/        package_name/            src/                classname.php       # vendor_name\package_name\classname            tests/                classnametest.php   # vendor_name\ Package_name\classnametest

Comparing these two structures, it is obvious that PSR-4 brings more concise file structure.

This article turns from: 1190000009368742

Laravel source parsing: PHP Automatic loading function principle analysis

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.