PHP的include和require

[复制链接]
发表于 2025-9-18 03:52:37 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
环境



  • Windows 11 专业版
  • XAMPP v3.3.0

    • PHP 8.2.12
    • Apache 2.4.58

  • VSCode 1.99.3
require和include

require 和 include 有点类似于C语言的 include 和Java的 import 。
比如,创建文件 test0504_util1.php 如下:
  1. <?php
  2. function add($a, $b) {
  3.     return $a + $b;
  4. }
  5. const PI = 3.14; // 注意全部用大写字母,且不加 `$` 前缀。
  6. $name = '张三';
  7. echo "我是util1" . PHP_EOL;
  8. ?>
复制代码
该PHP文件里:


  • 定义了 add() 函数
  • 定义了常量 PI
  • 定义了变量 $name
  • 有一段全局的代码
在同级目次里,创建文件 test0504_1.php 如下:
  1. <?php
  2. require 'test0504_util1.php';
  3. $x = add(1, 2);
  4. echo "x = $x" . PHP_EOL;
  5. echo "PI = " . PI . PHP_EOL;
  6. echo "name = $name" . PHP_EOL;
  7. ?>
复制代码
在该PHP文件里引入了 test0504_util1.php 文件。因此,就可以利用此中的函数、常量、变量。
运行结果如下:
  1. 我是util1
  2. x = 3
  3. PI = 3.14
  4. name = 张三
复制代码
留意,被引入文件的全局代码,也会被运行(本例中输出了 我是util1 )。
上面的例子里,引用文件利用了被引用文件的函数、常量、变量。反过来,被引用文件也可以利用引用文件的函数、常量、变量。
比如,可以把被引用文件看成一个模板,引用文件在引用模板前,先设置好数据。
一个典型的例子是页面的header。
创建文件 test0504_header1.php 如下:
  1. <head>
  2.     <title><?php
  3.     echo "当前页面:$title";
  4.     ?></title>
  5. </head>
复制代码
该文件是将要被引用的模板文件,此中有一个变量 $titile 。
创建文件 test0504_page1.php 如下:
  1. <html>
  2.     <?php
  3.         $title = 'page1';
  4.         require 'test0504_header1.php';
  5.     ?>
  6.     <body>
  7.         <p>这是页面1</p>
  8.     </body>
  9. </html>
复制代码
类似的,创建文件 test0504_page2.php 如下:
  1. <html>
  2.     <?php
  3.         $title = 'page2';
  4.         require 'test0504_header1.php';
  5.     ?>
  6.     <body>
  7.         <p>这是页面2</p>
  8.     </body>
  9. </html>
复制代码
在这两个文件中,先设置好 $title 变量的值,然后引用模板文件。
访问页面1:

访问页面2:

可见,二者的header是相同的模板,只是title的值差异。
require VS include

require 和 include 的重要区别在于,对于被引用文件不存在时的活动:


  • require :假如文件不存在,PHP 会抛出 E_COMPILE_ERROR ,并立即终止脚本:
  1. Fatal error: Uncaught Error: Failed opening required 'xxx.php' (include_path='C:\xampp\php\PEAR') in C:\xampp\htdocs\test0504_2.php:2
复制代码


  • include :假如文件不存在,PHP 会抛出 E_WARNING ,但脚本会继承实行后续代码:
  1. Warning: include(): Failed opening 'xxx.php' for inclusion (include_path='C:\xampp\php\PEAR') in C:\xampp\htdocs\test0504_2.php on line 3
复制代码
利用场景:


  • require :用于加载步伐运行必须的依靠(如数据库毗连、焦点函数库)。也就是“必须要有,没有不可”的文件
  • include :用于加载可选的模板文件或用户自定义内容。也就是“可有可无,没有也影响不大”的文件
require(include) VS require_once(include_once)

二者的区别在于,当重复引入同一个文件时:


  • require :会引入多次
  • require_once :只会引入一次
该利用 require 照旧 require_once ,取决于详细的应用场景。比如,同一个页面上确实需要多次表现同一个东西(比如一个 div 元素),那就在差异的位置利用require 来多次引入同一文件。假如是要引入类、变量、常量等,那显然应该利用 require_once ,以克制重复定义,辩说报错。
include 和 include_once 也同理。
路径问题

当前工作目次对相对路径的影响

在上面的例子里,引入的是同一目次里的文件,以是没有指定目次:
  1. require 'xxx.php';
复制代码
这里利用的是相对路径(相对于当前脚本文件)。
利用相对路径的问题是,假如“当前工作目次”发生了厘革,则相对路径所代表的绝对路径也改变了。
现有目次布局如下:
  1. htdocs
  2.     |----dir1
  3.     |  |----1.php
  4.     |----dir2
  5.        |----test0504_3.php
复制代码
在 1.php 里,定义了变量 $aaa :
  1. <?php
  2.     $aaa = 123;
  3. ?>
复制代码
在 test0504_3.php 里引入 1.php :
  1. <?php
  2.     require '../dir1/1.php';
  3.     echo $aaa . PHP_EOL;
  4. ?>
复制代码
在VSCode里运行,是没有问题的,在欣赏器里访问 http://localhost/dir2/test0504_3.php ,也没有问题。
修改文件如下:
  1. <?php
  2.     echo "__DIR__ : " . __DIR__ . PHP_EOL;
  3.     echo "get_include_path() : " . get_include_path() . PHP_EOL;
  4.     echo "getcwd() : " . getcwd() . PHP_EOL;
  5.     echo "realpath('../dir1/1.php') : " . realpath('../dir1/1.php') . PHP_EOL;
  6.     echo "stream_resolve_include_path('../dir1/1.php') : " . stream_resolve_include_path('../dir1/1.php') . PHP_EOL;
  7.     require '../dir1/1.php';
  8.     echo $aaa . PHP_EOL;
  9. ?>
复制代码
此中:


  • __DIR__ :脚本文件地点目次的绝对路径
  • get_include_path() :PHP查找文件的路径
  • getcwd() :当前工作目次
  • realpath() :获取目的路径的绝对路径(比如目的路径大概会含有 .. )
  • stream_resolve_include_path() :在 include_path 指定的目次列表中查找目的文件,并返回第一个匹配的绝对路径。若文件不存在,则返回 false
在VSCode里运行,输出结果是:
  1. __DIR__ : C:\xampp\htdocs\dir2
  2. get_include_path() : C:\xampp\php\PEAR
  3. getcwd() : C:\xampp\htdocs\dir2
  4. realpath('../dir1/1.php') : C:\xampp\htdocs\dir1\1.php
  5. stream_resolve_include_path('../dir1/1.php') : C:\xampp\htdocs\dir1\1.php
  6. 123
复制代码
假如在下令行里,在 dir2 目次下运行:
  1. PS C:\xampp\htdocs\dir2> php .\test0504_3.phpXdebug: [Step Debug] Time-out connecting to debugging client, waited: 200 ms. Tried: localhost:9003 (through xdebug.client_host/xdebug.client_port).__DIR__ : C:\xampp\htdocs\dir2
  2. get_include_path() : C:\xampp\php\PEAR
  3. getcwd() : C:\xampp\htdocs\dir2
  4. realpath('../dir1/1.php') : C:\xampp\htdocs\dir1\1.php
  5. stream_resolve_include_path('../dir1/1.php') : C:\xampp\htdocs\dir1\1.php
  6. 123
复制代码
可见和在VSCode运行是一样的。
注:输出结果里有个毗连超时,这是由于 php.ini 里设置了Xdebug。在下令行运行php,会导致Xdebug毗连debug client的错误(localhost:9003)。不过并不影响代码运行。加上 -n 选项,表现倒霉用 php.ini 设置,就不会提示这个信息了。
运行时加上 -n 选项(倒霉用 php.ini 设置文件):
  1. PS C:\xampp\htdocs\dir2> php -n .\test0504_3.php
  2. __DIR__ : C:\xampp\htdocs\dir2
  3. get_include_path() : .;C:\php\pear
  4. getcwd() : C:\xampp\htdocs\dir2
  5. realpath('../dir1/1.php') : C:\xampp\htdocs\dir1\1.php
  6. stream_resolve_include_path('../dir1/1.php') : C:\xampp\htdocs\dir1\1.php
  7. 123
复制代码
可见,加不加 -n ,影响的是 include_path 。
假如在 dir2 以外的目次里运行,就会出错。比如在 C:\ 目次运行:
  1. PS C:\> php -n C:\xampp\htdocs\dir2\test0504_3.php
  2. __DIR__ : C:\xampp\htdocs\dir2
  3. get_include_path() : .;C:\php\pear
  4. getcwd() : C:\
  5. realpath('../dir1/1.php') :
  6. stream_resolve_include_path('../dir1/1.php') :
  7. Warning: require(../dir1/1.php): Failed to open stream: No such file or directory in C:\xampp\htdocs\dir2\test0504_3.php on line 8
  8. Fatal error: Uncaught Error: Failed opening required '../dir1/1.php' (include_path='.;C:\php\pear') in C:\xampp\htdocs\dir2\test0504_3.php:8
  9. Stack trace:
  10. #0 {main}
  11.   thrown in C:\xampp\htdocs\dir2\test0504_3.php on line 8
复制代码
加不加 -n 选项都会报错,由于二者的 include_path 固然差异,但都没找到所需文件。
可见,当前工作目次是 C:\ 时,require语句出错了,由于找不到 ../dir1/1.php 文件。
题外话

假如不是在 dir2 目次里,而是在其父目次 htdocs 目次里创建 test0504_2.php 文件,并修改相对路径,如下:
  1. <?php
  2.     echo "__DIR__ : " . __DIR__ . PHP_EOL;
  3.     echo "get_include_path() : " . get_include_path() . PHP_EOL;
  4.     echo "getcwd() : " . getcwd() . PHP_EOL;
  5.     echo "realpath('dir1/1.php') : " . realpath('dir1/1.php') . PHP_EOL;
  6.     echo "stream_resolve_include_path('dir1/1.php') : " . stream_resolve_include_path('dir1/1.php') . PHP_EOL;
  7.     require 'dir1/1.php';
  8.     echo $aaa . PHP_EOL;
  9. ?>
复制代码
则不会报错:
  1. PS C:\> php -n C:\xampp\htdocs\test0504_2.php
  2. C:\
  3. 123
复制代码
明显当前工作目次照旧 C:\ ,利用相对路径 dir1/1.php 为什么不报错呢?
这会不会与XAMPP大概 php.ini 有关呢?但我实验克制了Apache,而且加上 -n 选项,以致把 php.ini 里Xdebug干系的设置都删掉了,但仍然是这样的活动。
我问了DeepSeek,它也答不出个以是然来,大概意思是说:


  • 对于非 ../ 开头的相对路径(如 dir1/1.php ),某些PHP版本会"智能"地实验从脚当地点目次分析
  • 对于 ../ 开头的路径,PHP出于安全思量会更严酷地仅基于当前工作目次分析
总结

不管怎么样,利用相对路径总是不靠谱的,照旧利用绝对路径吧。
  1. // 在任何文件中都这样写
  2. require __DIR__ . '/dir1/1.php';  // 当前脚本文件在 htdocs 目录下
  3. require __DIR__ . '/../dir1/1.php'; // 当前脚本文件在 htdocs/dir2 目录下
复制代码
这里利用了把戏常量 __DIR__ ,表现脚本文件的绝对路径。
通过利用 __DIR__ 再加上目的文件的相对路径,就得到了目的文件的绝对路径,这样做可以确保:


  • 不受工作目次影响
  • 不受 include_path 设置影响
  • 不受-n参数影响
其它

Windows和Linux的路径分隔符是差异的:


  • Windows: \
  • Linux: /
在上面的代码中,路径分隔符用的都是 / 。在Windows下运行也是没问题的。以是,不管什么操作体系,统一都用 / 好了。
注:假如需要,可以利用 DIRECTORY_SEPARATOR ,以适配差异操作体系,比如 'dir' . DIRECTORY_SEPARATOR . 'file.php' 。不过一样寻常没须要这么做,直接用 / 就行。
参考



  • https://www.php.net/docs.php
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表