在PHP中,有两种包含外部文件的方式,分别是include和require。他们之间有什么不同呢?

如果文件不存在或发生了错误,require产生E_COMPILE_ERROR级别的错误,程序停止运行。而include只产生警告,脚本会继续执行。

这就是它们最主要的区别,其他方面require基本等同于include。

  • 被包含文件先按参数给出的路径寻找,如果没有给出目录(只有文件名)时则按照 include_path 指定的目录寻找。如果在 include_path 下没找到该文件则 include 最后才在调用脚本文件所在的目录和当前工作目录下寻找
  • 如果定义了路径不管是绝对路径还是当前目录的相对路径 include_path 都会被完全忽略
  • include_path 在php.ini中定义
  • 当一个文件被包含时,其中所包含的代码继承了 include 所在行的变量范围。从该处开始,调用文件在该行处可用的任何变量在被调用的文件中也都可用。不过所有在包含文件中定义的函数和类都具有全局作用域

除了普通的require和include之外,还有require_once和include_once,他们的作用是:

  • 如果该文件中已经被包含过,则不会再次包含。如同此语句名字暗示的那样,只会包含一次
  • 可以用于在脚本执行期间同一个文件有可能被包含超过一次的情况下,想确保它只被包含一次以避免函数重定义,变量重新赋值等问题

我们来看些例子:


// a.php 不存在
include "a.php"; // warning
// require "a.php"; // error echo 111; // 使用include时111会输出 // file1.php 中只有一行代码echo 'file1';
require_once 'includeandrequire/file1.php'; // file1
require_once 'includeandrequire/file1.php'; // noting include_once 'includeandrequire/file1.php'; // noting
include_once 'includeandrequire/file1.php'; // noting require 'includeandrequire/file1.php'; // file1
require 'includeandrequire/file1.php'; // file1 require 'includeandrequire/file1.php'; // file1
require 'includeandrequire/file1.php'; // file1

我们可以看出当第一个_once加载成功后,后面不管是require_once还是include_once,都不会再加载这个文件了。而不带_once的则会重复加载文件。


file2.php <?php echo 'file2:' . $a, PHP_EOL;
echo 'file2:' . $b, PHP_EOL;
$b = "file2"; myFile.php <?php $a = 'myFile';
$b = 'youFile';
require_once 'includeandrequire/file2.php';
echo $a, PHP_EOL;
echo $b, PHP_EOL; // 输出结果
// file2:myFile
// file2:youFile
// myFile
// file2 file3.php
<?php $c = 'file3'; myFile.php
<?php
function test(){
require_once 'includeandrequire/file3.php';
echo $c, PHP_EOL; // file3
}
test();
echo $c, PHP_EOL; // empty

被包含文件中可以获取到父文件中的变量,父文件也可以获得包含文件中的变量,但是,需要注意_once的一个特殊情况。


function foo(){
require_once 'includeandrequire/file3.php';
return $c;
} for($a=1;$a<=5;$a++){
echo foo(), PHP_EOL;
} // file3
// empty
// empty
// empty
// empty

使用_once并循环加载时,只有第一次会输出file3.php中的内容,这是为什么呢?因为现在的变量范围作用域在方法中,第一次加载完成后,后面的的文件不会再被加载了,这时后面四次循环并没有$c被定义,$c默认就是空值了。

如果两个方法中同时用_once加载了一个文件,第二个方法还会加载吗?


function test1(){
require_once 'includeandrequire/file1.php';
}
function test2(){
require_once 'includeandrequire/file1.php';
}
test1(); // file1
test2(); // empty

抱歉,只有第一个方法会加载成功,第二个方法不会再次加载了。

那么,我们在日常的开发中,使用哪个更好呢?

  • 从效率来说,_once需要验证是否已经加载过文件,效率会低一些,但是并不是绝对的,甚至是我们肉眼不可见的降低,所以可以忽略它的效率问题。而它带来的好处则比不带_once的多得多
  • 本着错误提前的原则,使用require_once更好。因为将PHP报错级别调整为不显示警告后,include的警告信息会不可见,会带来不可预知的错误
  • 在方法中使用时,不应该用_once来加载文件,特别是这个文件需要在多个类或者方法中使用时,使用_once可能会导致后面的方法中无法载相同的文件
  • 使用require或include时,最好不要用括号,虽然的确可以这么使用,如 include ('xxx.php'); 它们是表达式关键字,不是系统方法,所以直接用 include 'xxx.php' 即可

include和require的文件如果有return,可以用变量接收retun回来的数据,另外它们还可以加载非PHP文件以及远程文件(远程加载需要确定php.ini中的allow_url_include为On),如:


file4.php
<?php return 'file4'; file4.txt
可以吧 myFile.php
<?php
$v = require 'includeandrequire/file4.php';
echo $v, PHP_EOL; // file4 include 'includeandrequire/file4.txt';
// 可以吧 include 'https://www.baidu.com/index.html';
// 百度首页的html代码

这下我们对于include和require的了解就非常深入了吧,这两个加载文件的方式并不复杂,但也很容易出现一些坑,特别是_once在方法中使用的时候一定要特别注意。最后,给一个小福利,封装一个一次性加载目录中所有文件的方法:


function include_all_once ($pattern) {
foreach (glob($pattern) as $file) {
require $file;
}
} include_all_once('includeandrequire/*');

测试代码:https://github.com/zhangyue0503/dev-blog/blob/master/php/201911/source/%E5%BD%BB%E5%BA%95%E6%90%9E%E6%98%8E%E7%99%BDPHP%E4%B8%AD%E7%9A%84include%E5%92%8Crequire.php

参考文档:

https://www.php.net/manual/zh/function.require.php

https://www.php.net/manual/zh/function.include.php

https://www.php.net/manual/zh/function.require-once.php

https://www.php.net/manual/zh/function.include-once.php

关注公众号:【硬核项目经理】获取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料

知乎、公众号、抖音、头条搜索【硬核项目经理】

B站ID:482780532

彻底搞明白PHP中的include和require的更多相关文章

  1. php 中使用include、require、include_once、require_once的区别

    在PHP中,我们经常会通过include.require.include_once.require_once来引用文件,都可以达到引用文件的目的,但他们之间又有哪些区别呢,接一下我们详细的介绍一下 i ...

  2. 真正搞明白Python中Django和Flask框架的区别

    在谈Python中Django框架和Flask框架的区别之前,我们需要先探讨如下几个问题. 一.为什么要使用框架? 为了更好地阐述这个问题,我们把开发一个应用的过程进行类比,往往开发一个应用(web应 ...

  3. PHP中的include和require

    1.include语句 使用include语句可以告诉PHP提取特定的文件,并载入它的全部内容 <?php inlude "fileinfo.php"; //此处添加其他代码 ...

  4. php中include()和require()的区别

    1.引用文件方式 对 include()来说,在include()执行时文件每次都要进行读取和评估:而对于require()来说,文件只处理一次(实际上,文件内容替换 了require()语句.这就意 ...

  5. php include 与 require 起底[转]

    转自 http://www.guangla.com/post/2014-01-24/40060857811 起因: 一朋友面试被问到,php的include和require的区别,这个可能是面试中出现 ...

  6. include 和require 区别

    include和require的区别  1.include() 包含文件 2.include_once(filename)如果已经包含,则不再执行include_once 3.requirerequi ...

  7. jsp中的@include与jsp:include区别详解

    1 前言 搞java开发的人也许都知道在jsp中引入项目中其他文件有如下两种方式 <%@include file="xxx.jsp"%> <jsp:include ...

  8. 相机拍的图,电脑上画的图,word里的文字,电脑屏幕,手机屏幕,相机屏幕显示大小一切的一切都搞明白了!

    相机拍的图,电脑上画的图,word里的文字,电脑屏幕,手机屏幕,相机屏幕显示大小一切的一切都搞明白了! 先说图片X×dpi=点数dotX是图片实际尺寸,简单点,我们只算图片的高吧,比如说拍了张图片14 ...

  9. 转:彻底搞清楚javascript中的require、import和export

    原文地址:彻底搞清楚javascript中的require.import和export   为什么有模块概念 理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块. 但是,Ja ...

随机推荐

  1. FIFO 深度了解

    嘻哈第二篇,深度聊聊各种细节. 优化与跨时钟阈分析

  2. 客户端连接mysql数据库反应慢

    远程客户端连接MysqL数据库太慢解决方案 局域网客户端访问mysql 连接慢问题解决 编辑mysql配置文件 # vi my.conf [mysqld] skip-name-resolve 重启my ...

  3. S3C2440—2.裸机开发步骤及工具使用

    文章目录 一.裸机开发步骤简介 1.在X86架构的Windows系统中 2.在X86架构的Ubuntu系统中 3.ARM裸机开发 二.soucre insight使用 1.sourec insight ...

  4. STM32—SPI详解

    目录 一.什么是SPI 二.SPI协议 物理层 协议层 1.通讯时序图 2.起始和停止信号 3.数据有效性 4.通讯模式 三.STM32中的SPI 简介 功能框图 1.通讯引脚 2.时钟控制逻辑 3. ...

  5. SQL 练习8

    查询「李」姓老师的数量 SELECT Tname,COUNT(Tname)数量 from Teacher GROUP BY tname HAVING Tname LIKE '李%'

  6. noip8

    T1 星际旅行 考试时觉得是道数学题,但没想到忘了欧拉路. 首先将每条边都拆成两条边,那么题目就变成了任意删掉两条边,使得新的图中存在欧拉路.设 \(sum\) 表示自环的数量, \(du_{i}\) ...

  7. 【springcloud】配置中心(Config-Server)

    转自:https://blog.csdn.net/pengjunlee/article/details/88061736 参考文章 Spring Cloud 配置中心为分布式系统中的服务器端和客户端提 ...

  8. ConcurrentModificationException异常原因和解决方法

    一.ConcurrentModificationException异常出现的原因 先看下面这段代码: public class Test { public static void main(Strin ...

  9. 使用volatile的条件

    使用volatile的值不能依赖于它之前的值: volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果. ...

  10. 利用AOP切面打印项目中每个接口的运行情况

    1.前言 AOP切面技术,大家应该都听知道,Spring框架的主要功能之一. AOP切面的用途很广,其中一个常见的用途就是打印接口方法的运行日志和运行时间. 日志对于一个项目很是重要,不仅有助于调错, ...