PHP中require和include路径问题详解


Posted in PHP onDecember 25, 2014

1 绝对路径、相对路径和未确定路径

相对路径

相对路径指以.开头的路径,例如

./a/a.php (相对当前目录)    

../common.inc.php (相对上级目录),

绝对路径

绝对路径是以 / 开头或者windows下的 C:/ 类似的盘符开头的路径,全路径不用任何参考路径就可以唯一确定文件的最终地址。 例如

/apache/wwwroot/site/a/a.php

c:/wwwroot/site/a/a.php

未确定路径

凡是不以 . 或者 / 开头、也不是windows下 盘符:/ 开头的路径,例如

a/a.php  

common.inc.php,

开始以为这也是相对路径,但在php的include/require包含机制中,这种类型的路径跟以 . 开头的相对路径处理是完全不同的。require './a.php' 和 require 'a.php' 是不同的!

下面分析这三种类型包含路径的处理方式:首先记住一个结论:如果包含路径为相对路径或者绝对径,则不会到include_path(php.ini中定义的include_path环境变量,或者在程序中使用set_include_path(...)设置)中去查找该文件。

测试环境说明

注意:下面的讨论和结论基于这样的环境: 假设 A=http://www.xxx.com/app/test/a.php,再次强调下面的讨论是针对直接访问A的情况。

2. 相对路径:
相对路径需要一个参考目录才能确定文件的最终路径,在包含解析中,不管包含嵌套多少层,这个参考目录是程序执行入口文件所在目录。

示例1

A中定义  require './b/b.php';  // 则B=[SITE]/app/test/b/b.php
B中定义  require './c.php';    // 则C=[SITE]/app/test/c.php 不是[SITE]/app/test/b/c.php

示例2

A中定义  require './b/b.php';  // 则B=[SITE]/app/test/b/b.php
B中定义  require '../c.php';   // 则C=[SITE]/app/c.php  不是 [SITE]/app/test/c.php

示例3

A中定义  require '../b.php';   //则B=[SITE]/app/b.php
B中定义  require '../c.php';   //则C=[SITE]/app/c.php  不是 [SITE]/c.php

示例4:

A中定义  require '../b.php';   // 则B=[SITE]/app/b.php
B中定义  require './c/c.php';  / /则C=[SITE]/app/test/c/c.php  不是 [SITE]/app/c/c.php

示例5

A中定义  require '../inc/b.php';  // 则B=[SITE]/app/inc/b.php
B中定义  require './c/c.php';     // 则C还是=[SITE]/app/test/c/c.php  不是 [SITE]/app/inc/c/c.php

示例6

A中定义  require '../inc/b.php';  // 则B=[SITE]/app/inc/b.php
B中定义  require './c.php';       // 则C=[SITE]/app/test/c.php  不是 [SITE]/app/inc/c.php

3. 绝对路径

绝对路径的比较简单,不容易混淆出错,require|inclue 的就是对应磁盘中的文件。

require '/wwwroot/xxx.com/app/test/b.php';    // Linux中
require 'c:/wwwroot/xxx.com/app/test/b.php';  // windows中
dirname(__FILE__)计算出来的也是一个绝对路径形式的目录,但是要注意__FILE__是一个Magic constants,不管在什么时候都等于写这条语句的php文件所在的绝对路径,因此dirname(__FILE__)也总是指向写这条语句的php文件所在的绝对路径,跟这个文件是否被其他文件包含使用没有任何关系。

示例1

A中定义  require '../b.php';                  // 则B=[SITE]/app/b.php
B中定义  require dirname(__FILE__).'/c.php';  // 则B=[SITE]/app/c.php

示例2

A中定义  require '../inc/b.php';              // 则B=[SITE]/app/inc/b.php
B中定义  require dirname(__FILE__).'/c.php';  // 则B=[SITE]/app/inc/c.php 始终跟B在同一个目录
结论:不管B是被A包含使用,还是直接被访问

B如果 require dirname(__FILE__).'/c.php';    // 则始终引用到跟B在同一个目录中的 c.php文件;
B如果 require dirname(__FILE__).'/../c.php'; // 则始终引用到B文件所在目录的父目录中的 c.php文件;
B如果 require dirname(__FILE__).'/c/c.php';  // 则始终引用到B文件所在目录的c子目录中的 c.php文件;

4. 未确定路径

首先在逐一用include_path中定义的包含目录来拼接[未确定路径],找到存在的文件则包含成功退出,如果没有找到,则用执行require语句的php文件所在目录来拼接[未确定路径]组成的全路径去查找该文件,如果文件存在则包含成功退出,否则表示包含文件不存在,出错。 未确定路径比较容易搞混不建议使用。

5. 解决方案

由于“相对路径”中的“参照目录”是执行入口文件所在目录,“未确定”路径也比较容易混淆,因此最好的解决方法是使用“绝对路径”; 例如b.php的内容如下,无论在哪里require b.php都是以b.php的路径为参照来require c.php的

$dir = dirname(__FILE__);
require($dir . '../c.php');
或者定义一个通用函数 import.php,将其设置为“自动提前引入文件”,在php.ini做如下配置

更改配置项(必须)auto_prepend_file = "C:\xampp\htdocs\auto_prepend_file.php"
更改配置项(可选)allow_url_include = On

import.php内容如下

function import($path) {    

    $old_dir = getcwd();        // 保存原“参照目录”

    chdir(dirname(__FILE__));    // 将“参照目录”更改为当前脚本的绝对路径

    require_once($path);

    chdir($old_dir);            // 改回原“参照目录”

}

这样就可以使用import()函数来require文件了,无论包含多少级“参照目录”都是当前文件

PHP 相关文章推荐
PHP+FLASH实现上传文件进度条相关文件 下载
Jul 21 PHP
php xml实例 留言本
Mar 20 PHP
php更改目录及子目录下所有的文件后缀的代码
Sep 24 PHP
php+highchats生成动态统计图
May 21 PHP
PHP的拦截器实例分析
Nov 03 PHP
PHP中一些可以替代正则表达式函数的字符串操作函数
Nov 17 PHP
Twig模板引擎用法入门教程
Jan 20 PHP
Apache无法自动跳转却显示目录的解决方法
Nov 30 PHP
php+js实现百度地图多点标注的方法
Nov 30 PHP
php安装扩展mysqli的实现步骤及报错解决办法
Sep 23 PHP
Thinkphp5.0 框架实现控制器向视图view赋值及视图view取值操作示例
Oct 12 PHP
如何用RabbitMQ和Swoole实现一个异步任务系统
May 29 PHP
Yii框架调试心得--在页面输出执行sql语句
Dec 25 #PHP
Web程序工作原理详解
Dec 25 #PHP
php更新mysql后获取改变行数的方法
Dec 25 #PHP
php常见的魔术方法详解
Dec 25 #PHP
php利用scws实现mysql全文搜索功能的方法
Dec 25 #PHP
php中heredoc与nowdoc介绍
Dec 25 #PHP
php中实现xml与mysql数据相互转换的方法
Dec 25 #PHP
You might like
PHP 图像尺寸调整代码
2010/05/26 PHP
php自定义hash函数实例
2015/05/05 PHP
学习php设计模式 php实现策略模式(strategy)
2015/12/07 PHP
关于php中的json_encode()和json_decode()函数的一些说明
2016/11/20 PHP
php解析非标准json、非规范json的方式实例
2020/12/10 PHP
JS类定义原型方法的两种实现的区别评论很多
2007/09/12 Javascript
浏览器常用高宽的jquery插件
2011/02/24 Javascript
网页编辑器ckeditor和ckfinder配置步骤分享
2012/05/24 Javascript
上传的js验证(图片/文件的扩展名)
2013/04/25 Javascript
详解JavaScript中的Unescape()和String() 函数
2015/11/09 Javascript
js字符限制(字符截取) 一个中文汉字算两个字符
2017/09/12 Javascript
Vue2.0子同级组件之间数据交互方法
2018/02/28 Javascript
nodeJs爬虫的技术点总结
2018/05/13 NodeJs
Node.js进阶之核心模块https入门
2018/05/23 Javascript
Vuex实现购物车小功能
2020/08/17 Javascript
VUE UPLOAD 通过ACTION返回上传结果操作
2020/09/07 Javascript
[06:45]DOTA2-DPC中国联赛 正赛 Magma vs LBZS 选手采访
2021/03/11 DOTA
Pyhthon中使用compileall模块编译源文件为pyc文件
2015/04/28 Python
浅谈Python中的作用域规则和闭包
2018/03/20 Python
使用TensorFlow实现二分类的方法示例
2019/02/05 Python
python之当你发现QTimer不能用时的解决方法
2019/06/21 Python
Eclipse配置python默认头过程图解
2020/04/26 Python
Python实现王者荣耀自动刷金币的完整步骤
2021/01/22 Python
简单介绍HTML5中的文件导入
2015/05/08 HTML / CSS
纽约手袋品牌:KARA
2018/03/18 全球购物
意大利网上药房:Farmacia 33
2020/01/27 全球购物
.net面试题
2016/09/17 面试题
工厂仓管员岗位职责
2014/01/01 职场文书
兰兰过桥教学反思
2014/02/08 职场文书
教师自我鉴定范文
2014/03/20 职场文书
法制宣传教育方案
2014/05/09 职场文书
小学感恩节活动策划方案
2014/10/06 职场文书
2015年银行柜员工作总结报告
2015/04/01 职场文书
老人院义工活动感想
2015/08/07 职场文书
Go语言基础map用法及示例详解
2021/11/17 Golang
MyBatis XPathParser解析器使用范例详解
2022/07/15 Java/Android