Please leave include_once and require_once

  • 2020-07-21 07:17:52
  • OfStack

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 the 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 has been included, return, otherwise the file open gets opened_path for this file. For example, in the above example, this file exists in "/ tmp2/2.php".

Then, after you have the opened_path, PHP goes to the list of loaded files to see if it is already included. If it is 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 file opening path (opened path)
3. Take opened path to EG(included_files) to find whether it exists. If it does, it will return
4. Compile file (compile_file)

This, in most cases, is not the problem, 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 for the actual file and system call for open.

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

Unfortunately, as I said, APC's include_once_override doesn't implement 1 well, and there are undefined issues like:


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

    a();
    a();
    ?>

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

    <?php
      class B {}
    ?>

If you open apc.include_ES113en_ES114en, you will get the following error:
Fatal error - include() : Cannot redeclare class

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.
So, don't use include_once


Related articles: