Home >Backend Development >PHP Tutorial >The mistake I always make using include_once instead of include

The mistake I always make using include_once instead of include

黄舟
黄舟Original
2017-06-25 11:47:322285browse

I have been using include_once since I learned the difference between include and include_once. I think it is only loaded once to avoid repeated loading. And it seems that I can't determine whether it has been loaded repeatedly. It turns out that I have been wrong all along.

In fact, there are advantages. If the project is developed by several people, include_once is better.

include_once execution order

Try to parse the absolute path of the file. If the parsing is successful, check EG (included_files). If it exists, return. If it does not exist, continue. Open the file and get the open path of the file. Take the opened path to EG (included_files) Search, whether it exists, if it exists, return, if it does not exist, continue to compile the file (compile_file

Recently, we have had several discussions about the removal of apc.include_once_override, and this APC configuration item has always been It has not been implemented well.

Here, I would like to share with you the reasons for this problem and some inspirations for us.

About using include or include_once (The following, all include require_once), this discussion is very long, and the conclusion has always been, that is, try to use include instead of include_once. In the past, the most common reason was that include_once needed to query the loaded file list. , confirm whether it exists, and then load it.

Admittedly, this reason is correct, but what I want to talk about today is another reason.

We know that PHP determines a Whether the file is loaded requires the opened_path of the file, which means, for example:

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

When PHP sees include_once "2.php", it does not know the actual path of the file. What, it is impossible to judge whether it has been loaded from the loaded file list, so in the implementation of include_once, it will first try to parse the real path of the file (for ordinary files, this parsing is just similar to checking getcwd and file path, so if is a relative path, generally it will not succeed), if the parsing is successful, search for EG (include_files), if it exists, it means it has been included, and return, otherwise open the file to get the opened_path of the file. For example, in the above example, this File exists in "/tmp2/2.php".

Then, after getting the opened_path, PHP goes to the loaded file list to find out whether it is included. If not, then compile directly, no need to open. file.

1. Try to parse the absolute path of the file. If the parsing is successful, check EG (included_files), return if it exists, and continue if it does not exist. 2. Open the file and get the open path of the file. )3. Take the open path and search it in EG (included_files) to see if it exists. If it exists, return it. If it does not exist, continue. 4. Compile the file (compile_file

In most cases, this is not a problem, but The problem is when you use APC...

When using APC, APC hijacks the compile file pointer of compile_file, thereby getting the compilation result directly from the cache, avoiding opening the actual file, and avoiding The system call to open.

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

But, unfortunately, as I said, APC's include_once_override has not been implemented well, and there will be some undefined problems, such as:

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

Then, our b.php is placed in "/tmp/b.php", the content is as follows:

<?phpclass B {}?>

Then when apc.include_once_override is turned on, continuous access will get the following error:

Fatal error - include() : Cannot redeclare class

(Postscript 2012-09-15 02:07:20: I have fixed this APC bug: #63070)

Excluding these technical factors, I have always believed that we should use include instead of include_once, because we can completely plan by ourselves, and a file will only be loaded once. We can also use Automatically load to do this.

If you use include_once, it only proves that you have no confidence in your own code.

So, I suggest you not to use include_once

The above is the detailed content of The mistake I always make using include_once instead of include. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn