백엔드 개발 PHP 튜토리얼 从php核心代码分析require和include的区别_php技巧

从php核心代码分析require和include的区别_php技巧

May 17, 2016 am 09:21 AM
include require

深入理解PHP之require/include顺序 http://www.jb51.net/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。

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

vue3+vite: src에서 이미지를 동적으로 가져오기 위해 require를 사용할 때 오류를 해결하는 방법 vue3+vite: src에서 이미지를 동적으로 가져오기 위해 require를 사용할 때 오류를 해결하는 방법 May 21, 2023 pm 03:16 PM

vue3+vite:src는 require를 사용하여 이미지를 동적으로 가져오고 vue3+vite는 여러 이미지를 동적으로 가져옵니다. vue3을 사용하는 경우 require는 이미지를 사용할 수 없습니다. imgUrl:require(' .../assets/test.png') 와 같은 vue2는 typescript가 require를 지원하지 않기 때문에 가져오므로 이를 해결하는 방법은 다음과 같습니다. waitimport를 사용합니다.

PHP include와 include_once의 차이점은 무엇입니까 PHP include와 include_once의 차이점은 무엇입니까 Mar 22, 2023 am 10:38 AM

PHP를 사용하여 웹 페이지를 작성할 때 때로는 현재 PHP 파일에 다른 PHP 파일의 코드를 포함해야 할 때가 있습니다. 이때, include 또는 include_once 함수를 사용하여 파일 포함을 구현할 수 있습니다. 그렇다면 include와 include_once의 차이점은 무엇입니까?

require의 용도는 무엇인가요? require의 용도는 무엇인가요? Nov 27, 2023 am 10:03 AM

require 사용법: 1. 모듈 소개: 많은 프로그래밍 언어에서 require는 외부 모듈이나 라이브러리를 소개하여 이들이 제공하는 기능을 프로그램에서 사용할 수 있도록 하는 데 사용됩니다. 예를 들어 Ruby에서는 require를 사용하여 타사 라이브러리나 모듈을 로드할 수 있습니다. 2. 클래스 또는 메서드 가져오기: 일부 프로그래밍 언어에서는 require를 사용하여 특정 클래스나 메서드를 현재 파일에서 사용할 수 있도록 가져옵니다. 3. 특정 작업 수행: 일부 프로그래밍 언어나 프레임워크에서는 특정 작업이나 기능을 수행하는 데 require가 사용됩니다.

PHP 헤더의 치명적인 오류를 해결하는 단계: require(): Failed opening require 'data/tdk.php' (include_path='.;C:\php\pear') PHP 헤더의 치명적인 오류를 해결하는 단계: require(): Failed opening require 'data/tdk.php' (include_path='.;C:\php\pear') Nov 27, 2023 pm 12:51 PM

PHP 헤더의 fatalerror:require():Failedopeningrequired'data/tdk.php'(include_path='.;C:phppear') 해결 단계 PHP를 사용하여 웹사이트나 애플리케이션을 개발할 때 다양한 오류가 자주 발생합니다. 일반적인 오류 중 하나는 "fatalerror:require():Failed"입니다.

PHP에서 require 키워드의 역할과 사용법에 대한 자세한 설명 PHP에서 require 키워드의 역할과 사용법에 대한 자세한 설명 Jun 28, 2023 pm 11:31 PM

PHP에서 require 키워드의 역할과 사용법에 대한 자세한 설명 PHP 개발에서 require는 매우 일반적으로 사용되는 키워드입니다. 그 기능은 현재 스크립트에서 사용하기 위해 지정된 파일을 포함하는 것입니다. 이번 글에서는 require 키워드의 기능과 사용법을 자세히 설명하겠습니다. 1. require 키워드의 역할 require 키워드는 현재 스크립트에 파일의 내용을 포함시킬 수 있습니다. 일반적으로 라이브러리 파일, 구성 파일 등과 같은 필요한 외부 파일을 포함하는 데 사용됩니다. 요구사항 사용

PHP 헤더의 치명적인 오류를 해결하는 단계: require(): 필수 'data/tdk.php'를 열지 못했습니다. PHP 헤더의 치명적인 오류를 해결하는 단계: require(): 필수 'data/tdk.php'를 열지 못했습니다. Nov 27, 2023 am 10:41 AM

PHP 헤더의 FatalError:require():Failedopeningrequired'data/tdk.php'를 해결하는 단계 PHP 웹사이트를 개발하고 유지 관리할 때 다양한 오류와 예외가 자주 발생합니다. 일반적인 오류 중 하나는 "FatalError:require():Failedopeningrequired'data/tdk.php'"입니다.

PHP 파일:// PHP 파일:// Aug 20, 2023 pm 06:13 PM

소개 PHP에서는 해당 내장 래퍼의 도움으로 다양한 URL 스타일 프로토콜을 파일 시스템 기능과 함께 사용할 수 있습니다. stream_wrapper_register() 함수를 사용하여 사용자 정의 래퍼를 정의할 수도 있습니다. PHP의 기본 래퍼는 로컬 파일 시스템을 나타내는 file://입니다. 다른 프로토콜이 명시적으로 사용되지 않으면 PHP 파서는 이를 파일 시스템 래퍼로 처리합니다. 파일 시스템 함수 fopen(), file_get_contents() 등에 전달된 파일 이름 매개변수는 기본적으로 file:// 프로토콜을 사용합니다. 파일 이름이 슬래시, 백슬래시 또는 Windows 드라이버로 시작하지 않는 경우

하나의 php.ini 파일을 다른 php.ini 파일에 포함시키는 방법은 무엇입니까? 하나의 php.ini 파일을 다른 php.ini 파일에 포함시키는 방법은 무엇입니까? Sep 02, 2023 pm 03:45 PM

기본 php,ini 파일에 .ini 파일을 포함할 수 없습니다. 대조적으로, PHP를 컴파일할 때 --with-config-file-scan-dir=PATH​​​​​&a 줄은

See all articles