PHP中require、require_once、include、include_once的区别
PHP中require、require_once、include、include_once的区别
前言
不知道有没有人和我一样,在说起这个四个语句有何不同的时候,能娓娓道来。但是真正在实际开发中,到底选择哪一个,要不要使用require()类似这种带括号的用法,能去正确地选择使用并且说出充分理由,成为一件令人头疼的事情。这就说明我们的认知只是停留在概念上,并不是真正地理解然后去使用它。
在这篇文章中,我们试着去分析这些语句的主要区别,以及借鉴一些目前PHP主流框架中的使用,去探讨我们在实际开发中该如何正确地去选择使用这些加载文件的语句。
概述
首先,要掌握这些基础知识
1、include/require是一种语言结构(语句)
include/require都是用来包含并运行指定文件的语句。像echo一样不是函数,可以这样用:require('file_path'),但是我们要清楚:它们不是真正的函数。
2、require、require_once、include、include_once 在php中都是用来加载文件的
3、带once和不带once的区别
1)如果该文件中已经被包含过,则不会再次包含。如同此语句名字暗示的那样,只会包含一次
2)可以用于在脚本执行期间同一个文件有可能被包含超过一次的情况下,想确保它只被包含一次以避免函数重定义,变量重新赋值等问题
举栗说明:
例1:使用_once并循环加载时,只有第一次会输出test1.php中的内容
1 test1.php 2 <?php 3 $c='test1'; 4 ?> 5 test.php 6 <?php 7 error_reporting(E_ALL ^ E_NOTICE); 8 //ini_set('display_errors','on'); 9 function foo() 10 { 11 require_once 'test1.php'; 12 return $c; 13 } 14 15 for ($a = 1; $a <= 5; $a++) { 16 echo foo().PHP_EOL; 17 } 18 19 //test1 20 //empty 21 //empty 22 //empty 23 //empty
例2: 如果两个方法中同时用_once加载了一个文件,第二个方法不会再次加载
1 test1.php 2 <?php 3 $c = 'test1'; 4 ?> 5 6 test.php 7 <?php 8 error_reporting(E_ALL ^ E_NOTICE); 9 //ini_set('display_errors','on'); 10 function foo1() 11 { 12 require_once 'test1.php'; 13 echo $c; 14 } 15 16 function foo2() 17 { 18 require_once 'test1.php'; 19 echo $c; 20 } 21 22 foo1(); //test1 23 foo2(); //empty
4、include()是有条件包含函数,而require()则是无条件包含函数(PHP5.3及以上版本,这点没有区别)
注意:这个根据测试,PHP5.3及以上版本,include和require在这点上面没有区别,都是有条件的包含函数。大家可以用下面的参考代码或者自己简单写一个,用不同的php版本测试下。
test.php
1 <?php 2 $flag=1; //$flag=0 再测试下 3 if ($flag){ 4 require 'test1.php'; 5 } 6 7 echo '888';
test1.php
1 <?php 2 echo 'test1'.PHP_EOL;
5、作用域
1) 当一个文件被包含时,其中所包含的代码继承了 include/require 所在行的变量范围。从该处开始,调用文件在该行处可用的任何变量在被调用的文件中也都可用。不过所有在包含文件中定义的函数和类都具有全局作用域。
1 vars.php 2 <?php 3 4 $color = 'green'; 5 $fruit = 'apple'; 6 7 ?> 8 9 test.php 10 <?php 11 12 echo "A $color $fruit"; // A 13 14 include 'vars.php'; 15 16 echo "A $color $fruit"; // A green apple 17 18 ?>
2)如果 include/require 出现于调用文件中的一个函数里,则被调用的文件中所包含的所有代码将表现得如同它们是在该函数内部定义的一样。所以它将遵循该函数的变量范围。此规则的一个例外是魔术常量,它们是在发生包含之前就已被解析器处理的。
1 <?php 2 3 function foo() 4 { 5 global $color; 6 7 include 'vars.php'; 8 9 echo "A $color $fruit"; 10 } 11 12 /* vars.php is in the scope of foo() so * 13 * $fruit is NOT available outside of this * 14 * scope. $color is because we declared it * 15 * as global. */ 16 17 foo(); // A green apple 18 echo "A $color $fruit"; // A green 19 20 ?>
主要区别
1、处理文件错误的机制
include : 如果文件不存在,会给出一个警告(Warning),但是脚本会继续执行
require :如果文件不存在,会报出一个致命错误(fatal error),脚本停止执行
如果通过页面访问的话,会报出500错误:
2、php性能
include:执行时文件每次都要进行读取和评估
require:文件只处理一次(实际上,文件内容替换了require()语句)
3、不同的使用弹性
include:一般是放在流程控制的处理区段中。PHP程式网页在读到 include的档案时,才将它读进来。这种方式,可以把程序执行时的流程简单化。
require:通常放在PHP程序的最前面,PHP程序在执行前,就会先读入require所指定引入的档案,使它变成PHP 程序网页的一部份。
实际使用场景
我们先看一下一些常用的PHP框架中的使用
1、Yii 2.0
从上图可以看出:require:引入文件,加载了 composer 自动生成的 ClassLoader类以及各种配置文件
2、Laravel 5.6
从上图可以看出:
1)require: 引入文件,注册加载 composer 自动生成的 class loader,包括所有composer require 的依赖
2)require_once:引入文件,生成容器 Container,Application 实例,并向容器注册核心组件(HttpKernel,ConsoleKernel,ExceptionHandler)。
3)这里可以看到定义一个变量$app来接收bootstrap/app.php文件中return回来的数据。
composer的ClassLoader.php中的部分代码:
通过上面所示部门主流PHP框架中加载文件的使用,我们可以大致分析出:
1、入口文件中,在引入composer的自动加载类的地方,用require来加载
2、在加载配置文件和核心框架类文件的时候,为了确保这些文件只被包含一次以避免函数重定义,变量重新赋值。使用require_once来加载
3、代码处理的过程中可以用include来将程序执行时的流程简单化
那么,我们在日常的开发中,使用哪个更好呢?
1)从效率来说,_once需要验证是否已经加载过文件,效率会低一些,但是并不是绝对的,甚至是我们肉眼不可见的降低,所以可以忽略它的效率问题。而它带来的好处则比不带_once的多得多
2)本着错误提前的原则,使用require_once更好。因为将PHP报错级别调整为不显示警告后,include的警告信息会不可见,会带来不可预知的错误
3)在方法中使用时,不应该用_once来加载文件,特别是这个文件需要在多个类或者方法中使用时,使用_once可能会导致后面的方法中无法载相同的文件
4 ) 使用require或include时,最好不要用括号,虽然的确可以这么使用,如 include ('xxx.php'); 它们是表达式关键字,不是系统方法,所以直接用 include 'xxx.php' 即可
5)include和require的文件如果有return,可以用变量接收return回来的数据,另外它们还可以加载非PHP文件以及远程文件
参考链接:
https://www.php.net/manual/zh/function.include.php
https://cloud.tencent.com/developer/article/1556823