Strong disclaimer: Do not use of include and require _once

  • 2020-06-07 04:20:27
  • OfStack

There is a long discussion about whether to use include or include_once(below, require_once is included), and the conclusion is as follows: try to use include instead of include_once. The most common reason in the past is that include_once needs to query the list of loaded files once to make sure it exists before loading.

Yes, that's the right reason, but I'm going to talk about another reason today.

As we know, PHP needs to get the opened_path of this file to determine whether a file has been loaded or not, which means, for example:


<?php
set_include_path("/tmp/:/tmp2/");
include_once("2.php");
?>

When PHP see include_once "2. php", he did not know what is the actual path of this file, also cannot from the loaded file list to determine whether already loaded, so in the implementation of include_once, will first try to resolve the real path of this file (for normal file this resolution is just similar check getcwd and file paths, so if it is a relative path, 1 kind is not successful), if the parsing is successful, Find EG(include_files), if it exists, it is included, return, otherwise open is the file, and get opened_path of this file. For example, in the above example, this file exists in "/ tmp2/2.php".

Then, after you have this opened_path, PHP goes to the list of loaded files to see if it is already included. If not, then compile, no more open file.

1. Try to resolve the absolute path of the file. If the resolution is successful, check EG(included_files)
2. Open the file to get the open path of the file (opened path)
3. Take opened path to EG(included_files) to find whether there is any. If there is, it will return
4. Compile file (compile_file)

This is not a problem in most cases, however the problem is when you use APC...

When using APC, APC hijacked the pointer to the compiled file compile_file to get the compilation result directly from cache, avoiding open to the actual file and system to open.

However, when you use include_once in the code, PHP has tried to go to open file before compile_file, and then enters compile file hijacked by APC, so that an additional open operation is generated. APC introduced include_once_override to solve this problem. When include_once_override is turned on, APC will hijack es97EN_ES98en_ES99en_ES101en handler to determine the absolute path of the file through stat, and then if it is not loaded, it will rewrite opcode as include to make an tricky solution.

Unfortunately, as I said, the include_once_override implementation of APC does not work well with 1 undefined issues, such as:


<?php
set_include_path("/tmp");
function a($arg = array()) {
    include_once("b.php");
}
a();
a();
?>

Then, our ES116en. php is placed on "/tmp/ ES119en. php", which reads as follows:

<?php
  class B {}
?>

If you open ES124en.include_ES126en_ES127en, you will get the following error:

Fatal error - include() : Cannot redeclare class b

Apart from these technical factors, I also think that we should use include instead of include_once, because we can do our own planning and only load a file once. We can also use automatic loading to do this.

Using include_once only proves that you have no confidence in your code.

Therefore, it is recommended that you stop using include_once


Related articles: