In a large Web project, Include_path is fundamental to a modular design (and of course, there are many autoload-based designs that do not affect this article), but precisely because of Include_path, It often leads us to a seemingly "bizarre" problem caused by not finding the right file.
There are also the following questions:
How does the include_path work?
What if there is more than one include_path order?
Under what circumstances does include_path not work?
Today, I would like to introduce this issue in a comprehensive way, let's start with an example.
The directory structure is as follows:
Root ├1.php ├3.php └subdir ├2.php └3.php
In 1.php:
The code is as follows:
<?php ini_set ("Include_path", ".:p ath_to_subdir"); Require ("2.php");?>
And in 2.php:
<?php require ("3.php");?>
And in the root directory 3.php print out "root", in the SubDir directory of 3.php print out "subdir";
Now, here's my question:
1. What output will I get when I run 1.php in the root directory?
2. What output will I get if I run the 1.php of the previous level directory under SubDir?
3. When canceling the current directory in Include_path path (that is, include_path= "Path_to_subdir"), what is the output of the above two problems?
Include_path in PHP
When PHP encounters the instruction of require (_once)/include (_once), it first makes the following judgment: is the file path to be included an absolute path?
If it is, it is included directly and ends.
If not, enter another logic (after multiple calls, the macro expands and enters _php_stream_fopen_with_path) to find this file
Next, in _php_stream_fopen_with_path, the following judgments are made:
The file path to include is a relative path (shaped as./file,.. /dir/file, the following "directory relative path instead")?
If it is, then skip the include_path's function logic and parse the relative path directly (described later separately)
A list of directories to be selected based on the include_path, and the path of the currently executing file, for example in the previous case of the article, will form a list of the following to be selected
The code is as follows:
".:p Ath_to_subdir:current_script_dir
Then, starting with the head of the list to be selected, take a path from the list to be selected, based on Default_dir_separator (":"), and then append the file name you want to include to the path, and try it. Returns if successful, otherwise continues with the next selected path.
So far, we have been able to answer the 3 questions I have raised at the beginning.
1. Because it is executed in the root directory, when 2.php is included in the 1.php, Include_path's second selected path plays a role (Path_to_subdir), finds the path_to_subdir/2.php, While the 2.php contains 3.php, the current working directory is root, so in the case of 3.php, Include_path's first choice of path "." Matching files found under (current working directory), so the resulting output is "root".
2. The same 1, except that the current path is subdir, so the resulting output is "subdir".
3. Because there is no current path for include_path, so when the root directory is running when 2.php contains 3.php, it is Path_to_subdir played a role, so both root and SubDir will get "subdir" output.
And if you empty the include_path in 2.php,
<?php ini_set ("Include_path", "); Require ("3.php");?>
Then it will be Current_script_dir function, and this time Current_script_dir is the path of 2.php, so still will get "subdir" output.
Directory relative path
In the case of a directory-relative path, the base point of the relative path is always the current working directory.
To illustrate the situation under the directory relative path, let's look at an illustration, or the above directory structure, but 1.php becomes:
<?php ini_set ("Include_path", "/"); Require ("./subdir/2.php");?>
2.php has become:
<?php require ("./3.php");?>
If executed in the root directory, looking for 3.php in 2.php will be found in the relative path of the current directory, so the resulting output is "root", and if it is executed under SubDir 1.php (php-f) of the previous level directory. /1.php), will exit abnormally because "./subdir/2.php" could not be found under SubDir.
Postscript
1. Because of the use of include_path and relative paths, performance will be related to the number of searches, worst case, if you have 10 include_path, then you may retry 11 times to find the files to include, so, Absolute paths are best used where absolute paths can be used.
2. Because the basedir of the relative path of the directory is always the current working path, if it is to be used, it needs to be related to the actual deployment path, so it is seldom used (of course, there are modules done with chdir).
3. In a modular system design, it is common to use the absolute path within the module by obtaining the module's deployment path (DirName (FILE), php5.3 later providing the DIR constant).