马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
环境
- Windows 11 专业版
- XAMPP v3.3.0
- VSCode 1.99.3
require和include
require 和 include 有点类似于C语言的 include 和Java的 import 。
比如,创建文件 test0504_util1.php 如下:
- <?php
- function add($a, $b) {
- return $a + $b;
- }
- const PI = 3.14; // 注意全部用大写字母,且不加 `$` 前缀。
- $name = '张三';
- echo "我是util1" . PHP_EOL;
- ?>
复制代码 该PHP文件里:
- 定义了 add() 函数
- 定义了常量 PI
- 定义了变量 $name
- 有一段全局的代码
在同级目次里,创建文件 test0504_1.php 如下:
- <?php
- require 'test0504_util1.php';
- $x = add(1, 2);
- echo "x = $x" . PHP_EOL;
- echo "PI = " . PI . PHP_EOL;
- echo "name = $name" . PHP_EOL;
- ?>
复制代码 在该PHP文件里引入了 test0504_util1.php 文件。因此,就可以利用此中的函数、常量、变量。
运行结果如下:
- 我是util1
- x = 3
- PI = 3.14
- name = 张三
复制代码 留意,被引入文件的全局代码,也会被运行(本例中输出了 我是util1 )。
上面的例子里,引用文件利用了被引用文件的函数、常量、变量。反过来,被引用文件也可以利用引用文件的函数、常量、变量。
比如,可以把被引用文件看成一个模板,引用文件在引用模板前,先设置好数据。
一个典型的例子是页面的header。
创建文件 test0504_header1.php 如下:
- <head>
- <title><?php
- echo "当前页面:$title";
- ?></title>
- </head>
复制代码 该文件是将要被引用的模板文件,此中有一个变量 $titile 。
创建文件 test0504_page1.php 如下:
- <html>
- <?php
- $title = 'page1';
- require 'test0504_header1.php';
- ?>
- <body>
- <p>这是页面1</p>
- </body>
- </html>
复制代码 类似的,创建文件 test0504_page2.php 如下:
- <html>
- <?php
- $title = 'page2';
- require 'test0504_header1.php';
- ?>
- <body>
- <p>这是页面2</p>
- </body>
- </html>
复制代码 在这两个文件中,先设置好 $title 变量的值,然后引用模板文件。
访问页面1:
访问页面2:
可见,二者的header是相同的模板,只是title的值差异。
require VS include
require 和 include 的重要区别在于,对于被引用文件不存在时的活动:
- require :假如文件不存在,PHP 会抛出 E_COMPILE_ERROR ,并立即终止脚本:
- 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 ,但脚本会继承实行后续代码:
- 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 也同理。
路径问题
当前工作目次对相对路径的影响
在上面的例子里,引入的是同一目次里的文件,以是没有指定目次:
这里利用的是相对路径(相对于当前脚本文件)。
利用相对路径的问题是,假如“当前工作目次”发生了厘革,则相对路径所代表的绝对路径也改变了。
现有目次布局如下:
- htdocs
- |----dir1
- | |----1.php
- |----dir2
- |----test0504_3.php
复制代码 在 1.php 里,定义了变量 $aaa :
在 test0504_3.php 里引入 1.php :
- <?php
- require '../dir1/1.php';
- echo $aaa . PHP_EOL;
- ?>
复制代码 在VSCode里运行,是没有问题的,在欣赏器里访问 http://localhost/dir2/test0504_3.php ,也没有问题。
修改文件如下:
- <?php
- echo "__DIR__ : " . __DIR__ . PHP_EOL;
- echo "get_include_path() : " . get_include_path() . PHP_EOL;
- echo "getcwd() : " . getcwd() . PHP_EOL;
- echo "realpath('../dir1/1.php') : " . realpath('../dir1/1.php') . PHP_EOL;
- echo "stream_resolve_include_path('../dir1/1.php') : " . stream_resolve_include_path('../dir1/1.php') . PHP_EOL;
- require '../dir1/1.php';
- echo $aaa . PHP_EOL;
- ?>
复制代码 此中:
- __DIR__ :脚本文件地点目次的绝对路径
- get_include_path() :PHP查找文件的路径
- getcwd() :当前工作目次
- realpath() :获取目的路径的绝对路径(比如目的路径大概会含有 .. )
- stream_resolve_include_path() :在 include_path 指定的目次列表中查找目的文件,并返回第一个匹配的绝对路径。若文件不存在,则返回 false
在VSCode里运行,输出结果是:
- __DIR__ : C:\xampp\htdocs\dir2
- get_include_path() : C:\xampp\php\PEAR
- getcwd() : C:\xampp\htdocs\dir2
- realpath('../dir1/1.php') : C:\xampp\htdocs\dir1\1.php
- stream_resolve_include_path('../dir1/1.php') : C:\xampp\htdocs\dir1\1.php
- 123
复制代码 假如在下令行里,在 dir2 目次下运行:
- 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
- get_include_path() : C:\xampp\php\PEAR
- getcwd() : C:\xampp\htdocs\dir2
- realpath('../dir1/1.php') : C:\xampp\htdocs\dir1\1.php
- stream_resolve_include_path('../dir1/1.php') : C:\xampp\htdocs\dir1\1.php
- 123
复制代码 可见和在VSCode运行是一样的。
注:输出结果里有个毗连超时,这是由于 php.ini 里设置了Xdebug。在下令行运行php,会导致Xdebug毗连debug client的错误(localhost:9003)。不过并不影响代码运行。加上 -n 选项,表现倒霉用 php.ini 设置,就不会提示这个信息了。
运行时加上 -n 选项(倒霉用 php.ini 设置文件):
- PS C:\xampp\htdocs\dir2> php -n .\test0504_3.php
- __DIR__ : C:\xampp\htdocs\dir2
- get_include_path() : .;C:\php\pear
- getcwd() : C:\xampp\htdocs\dir2
- realpath('../dir1/1.php') : C:\xampp\htdocs\dir1\1.php
- stream_resolve_include_path('../dir1/1.php') : C:\xampp\htdocs\dir1\1.php
- 123
复制代码 可见,加不加 -n ,影响的是 include_path 。
假如在 dir2 以外的目次里运行,就会出错。比如在 C:\ 目次运行:
- PS C:\> php -n C:\xampp\htdocs\dir2\test0504_3.php
- __DIR__ : C:\xampp\htdocs\dir2
- get_include_path() : .;C:\php\pear
- getcwd() : C:\
- realpath('../dir1/1.php') :
- stream_resolve_include_path('../dir1/1.php') :
- 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
- Fatal error: Uncaught Error: Failed opening required '../dir1/1.php' (include_path='.;C:\php\pear') in C:\xampp\htdocs\dir2\test0504_3.php:8
- Stack trace:
- #0 {main}
- 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 文件,并修改相对路径,如下:
- <?php
- echo "__DIR__ : " . __DIR__ . PHP_EOL;
- echo "get_include_path() : " . get_include_path() . PHP_EOL;
- echo "getcwd() : " . getcwd() . PHP_EOL;
- echo "realpath('dir1/1.php') : " . realpath('dir1/1.php') . PHP_EOL;
- echo "stream_resolve_include_path('dir1/1.php') : " . stream_resolve_include_path('dir1/1.php') . PHP_EOL;
- require 'dir1/1.php';
- echo $aaa . PHP_EOL;
- ?>
复制代码 则不会报错:
- PS C:\> php -n C:\xampp\htdocs\test0504_2.php
- C:\
- 123
复制代码 明显当前工作目次照旧 C:\ ,利用相对路径 dir1/1.php 为什么不报错呢?
这会不会与XAMPP大概 php.ini 有关呢?但我实验克制了Apache,而且加上 -n 选项,以致把 php.ini 里Xdebug干系的设置都删掉了,但仍然是这样的活动。
我问了DeepSeek,它也答不出个以是然来,大概意思是说:
- 对于非 ../ 开头的相对路径(如 dir1/1.php ),某些PHP版本会"智能"地实验从脚当地点目次分析
- 对于 ../ 开头的路径,PHP出于安全思量会更严酷地仅基于当前工作目次分析
总结
不管怎么样,利用相对路径总是不靠谱的,照旧利用绝对路径吧。
- // 在任何文件中都这样写
- require __DIR__ . '/dir1/1.php'; // 当前脚本文件在 htdocs 目录下
- require __DIR__ . '/../dir1/1.php'; // 当前脚本文件在 htdocs/dir2 目录下
复制代码 这里利用了把戏常量 __DIR__ ,表现脚本文件的绝对路径。
通过利用 __DIR__ 再加上目的文件的相对路径,就得到了目的文件的绝对路径,这样做可以确保:
- 不受工作目次影响
- 不受 include_path 设置影响
- 不受-n参数影响
其它
Windows和Linux的路径分隔符是差异的:
在上面的代码中,路径分隔符用的都是 / 。在Windows下运行也是没问题的。以是,不管什么操作体系,统一都用 / 好了。
注:假如需要,可以利用 DIRECTORY_SEPARATOR ,以适配差异操作体系,比如 'dir' . DIRECTORY_SEPARATOR . 'file.php' 。不过一样寻常没须要这么做,直接用 / 就行。
参考
- https://www.php.net/docs.php
|