Home Backend Development PHP Tutorial 从php核心代码分析require和include的区别_PHP

从php核心代码分析require和include的区别_PHP

Jun 01, 2016 pm 12:17 PM
include require

深入理解PHP之require/include顺序 http://www.bitsCN.com/article/25867.htm
普及
在php手册中:

require() is identical to include() except upon failure it will also produce a fatal E_ERROR level error. In other words, it will halt the script whereas include() only emits a warning (E_WARNING) which allows the script to continue.

就是说在失败的时候,require是会中止php运行的,而include是可以继续运行的。
倒底有什么样的区别呢?我们带着这个疑问来一起进入PHP的核心代码。
下面是一个PHP运行过程的图(这个图是出自哪里的?鸟哥画的?)
php

补习一下:lex是代码扫描器,扫描代码用的,yacc是Yet Another Compiler Compiler,作用是把任何一种代码的语法转成yacc语法,yacc就是解析器(真TMD绕)。
lex在c下的后缀是*.l yacc是*.y

正题
下面看操作记录:

cc@cc-laptop:/opt/workspace$ svn checkout http://svn.php.net/repository/php/php-src/branches/PHP_5_3 php-src-5.3
从svn取最新的php源代码。

开始深入:

cc@cc-laptop:/opt/workspace/php-src-5.3$ find . -type f -name “*.l” -exec grep -Hn “require_once” {} \;
./Zend/zend_language_scanner.l:1093:”require_once” {
寻找lex代码扫描器文件中出现require_once的地方,zend_language_scanner.l的1093行。
1093 “require_once” {
1094 return T_REQUIRE_ONCE;
1095 }

然后再搜一下T_REQUIRE_ONCE,

cc@cc-laptop:/opt/workspace/php-src-5.3$ find . -type f -name “*.y” -exec grep -Hn “T_INCLUDE” {} \;
./Zend/zend_language_parser.y:52:%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
./Zend/zend_language_parser.y:985: | T_INCLUDE expr { zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); }
./Zend/zend_language_parser.y:986: | T_INCLUDE_ONCE expr { zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); }

在985行附近,有这样一群代码:

internal_functions_in_yacc:
T_ISSET ‘(‘ isset_variables ‘)' { $$ = $3; }
| T_EMPTY ‘(‘ variable ‘)' { zend_do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 TSRMLS_CC); }
| T_INCLUDE expr { zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); }
| T_INCLUDE_ONCE expr { zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); }
| T_EVAL ‘(‘ expr ‘)' { zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); }
| T_REQUIRE expr { zend_do_include_or_eval(ZEND_REQUIRE, &$$, &$2 TSRMLS_CC); }
| T_REQUIRE_ONCE expr { zend_do_include_or_eval(ZEND_REQUIRE_ONCE, &$$, &$2 TSRMLS_CC); }
;

于是乎,我们需要继续深入寻找zend_do_include_or_eval,

cc@cc-laptop:/opt/workspace/php-src-5.3$ find . -type f -name “*.c” -exec grep -Hn “zend_do_include_or_eval” {} \;
./Zend/zend_compile.c:4317:void zend_do_include_or_eval(int type, znode *result, const znode *op1 TSRMLS_DC) /* {{{ */

zend_do_include_or_eval中组装了一个结构体,ZEND_INCLUDE_OR_EVAL。

再在zend_vm_def.h中找到ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY):
switch (Z_LVAL(opline->op2.u.constant)) {代码略}

中间关键的一句是:
new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);

在zend_complie.h文件中:
ZEND_API zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC);

这个函数定义在zend_language_scaner.l文件中,找出最核心的代码:

if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) {
// require与include的差别:错误信息的显示级别(有bailout和无bailout)
if (type==ZEND_REQUIRE) { //require时
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
zend_bailout();
} else {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
}
compilation_successful=0;
} else {代码略}

继续追踪zend_message_dispatcher可以在main/main.c文件中找到php_message_handler_for_zend函数:

//include输出错误信息时的级别为:E_WARNING
case ZMSG_FAILED_INCLUDE_FOPEN:
php_error_docref(“function.include” TSRMLS_CC, E_WARNING, “Failed opening ‘%s' for inclusion (include_path='%s')”, php_strip_url_passwd((char *) data), STR_PRINT(PG(include_path)));
break;
//require输出错误信息时的级别为:E_COMPILE_ERROR
代码略

总结
和开头PHP手册所说完全一致,require和include的区别在于,出现错误时,一个是error一个是warning。

Statement of this Website
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

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: How To Unlock Everything In MyRise
1 months ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

vue3+vite: How to solve the error when using require to dynamically import images in src vue3+vite: How to solve the error when using require to dynamically import images in src May 21, 2023 pm 03:16 PM

vue3+vite:src uses require to dynamically import images and error reports and solutions. vue3+vite dynamically imports multiple images. If vue3 is using typescript development, require will introduce image errors. requireisnotdefined cannot be used like vue2 such as imgUrl:require(' .../assets/test.png') is imported because typescript does not support require, so import is used. Here is how to solve it: use awaitimport

What is the difference between php include and include_once What is the difference between php include and include_once Mar 22, 2023 am 10:38 AM

When we write web pages using PHP, sometimes we need to include code from other PHP files in the current PHP file. At this time, you can use the include or include_once function to implement file inclusion. So, what is the difference between include and include_once?

What are the uses of require? What are the uses of require? Nov 27, 2023 am 10:03 AM

Usage of require: 1. Introduce modules: In many programming languages, require is used to introduce external modules or libraries so that the functions they provide can be used in the program. For example, in Ruby, you can use require to load third-party libraries or modules; 2. Import classes or methods: In some programming languages, require is used to import specific classes or methods so that they can be used in the current file; 3. Perform specific tasks: In some programming languages ​​or frameworks, require is used to perform specific tasks or functions.

Steps to solve the fatal error in the php header: require(): Failed opening required 'data/tdk.php' (include_path='.;C:\php\pear') Steps to solve the fatal error in the php header: require(): Failed opening required 'data/tdk.php' (include_path='.;C:\php\pear') Nov 27, 2023 pm 12:51 PM

Steps to resolve fatalerror:require():Failedopeningrequired'data/tdk.php'(include_path='.;C:phppear') in PHP header When developing websites or applications using PHP, we often encounter various errors . One of the common errors is "fatalerror:require():Failed

Detailed explanation of the role and usage of the require keyword in PHP Detailed explanation of the role and usage of the require keyword in PHP Jun 28, 2023 pm 11:31 PM

Detailed explanation of the role and usage of the require keyword in PHP In PHP development, require is a very commonly used keyword. Its function is to include the specified file for use by the current script. This article will explain in detail the function and use of the require keyword. 1. The role of the require keyword The require keyword can include the contents of a file into the current script. It is usually used to include some necessary external files, such as library files, configuration files, etc. Use req

Steps to solve fatal error in php header: require(): Failed opening required 'data/tdk.php' Steps to solve fatal error in php header: require(): Failed opening required 'data/tdk.php' Nov 27, 2023 am 10:41 AM

Steps to resolve FatalError:require():Failedopeningrequired'data/tdk.php' in PHP header When developing and maintaining PHP websites, we often encounter various errors and exceptions. One of the common errors is "FatalError:require():Failedopeningrequired'data/tdk.php'".

PHP file:// PHP file:// Aug 20, 2023 pm 06:13 PM

Introduction In PHP, various URL style protocols can be used in conjunction with file system functions, with the help of corresponding built-in wrappers. Custom wrappers can also be defined using the stream_wrapper_register() function. The default wrapper in PHP is file://, which represents the local file system. If no other protocol is explicitly used, the PHP parser will treat it as a filesystem wrapper. The file name parameters passed to the file system functions fopen(), file_get_contents(), etc. use the file:// protocol by default. When the file name does not begin with a forward slash, a backslash, or the driver in Windows

How to include one php.ini file within another php.ini file? How to include one php.ini file within another php.ini file? Sep 02, 2023 pm 03:45 PM

Unable to include .ini file in main php,ini file. In contrast, when compiling PHP, the line --with-config-file-scan-dir=PATH​​​​​&a

See all articles