PHP中你应该知道的require()文件包含的正确用法


Posted in PHP onJune 12, 2015

以前看一些PHP框架源码的时候,很奇怪在文件包含的时候,会用dirname(__FILE__)来拼凑文件路径,不知道这样做有什么好处,后来终于发现了其中的缘由。

我们来看一个简单的例子:

有a,b,c三个php文件。a.php在网站根目录,b.php在b文件夹下——b/b.php,c.php在c文件夹下——c/c.php。有些混乱?看图就一目了然了:

PHP中你应该知道的require()文件包含的正确用法

a.php 和 b.php 都包含了 c.php,最后 c.php 包含了d文件夹下的一个php文件——d/d.php。

我们先来看a.php:

<?php 
  $file_name = 'a.php';
  echo "this is a.php";
  echo "<hr>";
  require('c/c.php');
 ?>

很简单的代码,打印输出后,包含了c/c.php,接着,我们需要看c/c.php:

<?php 
  $c_file_name = 'c.php';
  echo 'this is c.php, is required by ' . $file_name;
  echo "<hr>";
  require('../d/d.php');
 ?>

打印输出 "this is c.php, is required by a.php",$file_name是在a.php中定义的变量。在最后,包含了d.php。因为d文件夹在当前c.php文件的上一层,所以,按照常理,我们会理所当然的把路径写成 "../d/d.php"。但是很遗憾,会报错。原因在于,在被包含的文件中如c.php,再去包含其他文件,路径是相对于最外层的父文件来说的,也就是相对于a.php,可以理解为因为你被我包含了,所以你要以我为准。看起来很玄乎,原理其实很简单:你可以把 require('c/c.php'); 看成是c/c.php文件里的代码,这样我们的a.php看起来可以是这个样子:

<?php 
  $file_name = 'a.php';
  echo "this is a.php";
  echo "<hr>";
  // require('c/c.php');
  $c_file_name = 'c.php';
  echo 'this is c.php, is required by ' . $file_name;
  echo "<hr>";
  require('../d/d.php');
 ?>

到此,你可以看到,我们要包含d/d.php文件时,刚才的路径是不是错误的了?因为,现在是在a.php的代码里,我们是相对于a.php文件来说的,当然,路径应该是 require('d/d.php'); 才对了。我们修改代码如下:

<?php 
  $file_name = 'a.php';

  echo "this is a.php";
  echo "<hr>";

  // require('c/c.php');
  $c_file_name = 'c.php';

  echo 'this is c.php, is required by ' . $file_name;
  echo "<hr>";

  require('d/d.php');
 ?>

此时,你还没有领悟到深意,需要往下看,我们再看b/b.php:

<?php 
  $file_name = 'b.php';
  echo "this is b.php";
  echo "<hr>";
  
  require('../c/c.php');
 ?>

不需要解释了吧,没啥问题,但是当你把 require('../c/c.php'); 换成 c/c.php 里面的代码的时候,你就会发现问题了,注意,我们刚才修改了c/c.php里的代码,把 require('../d/d.php'); 改成了 require('d/d.php'); 看下面包含进来后的代码:

<?php 
  $file_name = 'b.php';
  echo "this is b.php";
  echo "<hr>";
  
  // require('../c/c.php');
  $c_file_name = 'c.php';
  echo 'this is c.php, is required by ' . $file_name;
  echo "<hr>";
  require('d/d.php');
 ?>

那么,相对于 b/b.php 来说,require('d/d.php'); 的路径错了,应该是 require('../d/d.php'); 才对。你回去修改 c/c.php 中的require路径,但是不对呀,你改了之后,b/b.php可以正常运行了,但是 a/a.php 又不行了,是不是,它们共用 c/c.php ,牵一发动全身,怎么办呢。

这个时候,我们回到文章开头提到的 dirname(__FILE__),这可是个好东西,可以完全解决以上问题。用了它,就可以不用关心包含你的文件是哪个文件、在哪个路径下面了,不需要顾虑父文件所在的层级,因为,dirname(__FILE__)可以相对于当前文件指定路径。也就是说,我们需要将我们的 c/c.php 中的 require 路径换为:

<?php 
  $c_file_name = 'c.php';

  echo 'this is c.php, is required by ' . $file_name;
  echo "<hr>";

  require(dirname(__FILE__) . '/../d/d.php');
 ?>

这里,我们只需要把 c/c.php 作为参照,相对于它来说,d/d.php 在上一层。这样,就只有一个标准了,那就是,以我为准,管你包含我,还是他包含我,我只以我自己为准,我要包含的文件只相对于我自己而言了。

对于 dirname(__FILE__) 不明白的同修,请google,很简单。

好了,PHP技术分享到此结束,有任何疑问或有错误之处,请留言。话说,这是我的第一个标准技术博文。第一篇是水文,第二篇是准技术,今天终于写了篇技术的,欧也。

PHP 相关文章推荐
真正面向对象编程:PHP5.01发布
Oct 09 PHP
MySQL GBK→UTF-8编码转换
May 24 PHP
Zend framework处理一个http请求的流程分析
Feb 08 PHP
常见的PHP五种设计模式小结
Mar 23 PHP
基于PHP CURL获取邮箱地址的详解
Jun 03 PHP
解析php中array_merge与array+array的区别
Jun 21 PHP
php生成数组的使用示例 php全组合算法
Jan 16 PHP
php实现的zip文件内容比较类
Sep 24 PHP
PHP获取文件夹大小函数用法实例
Jul 01 PHP
Yii2针对指定url的生成及图片等的引入方法小结
Jul 18 PHP
PHP制作登录异常ip检测功能的实例代码
Nov 16 PHP
解决laravel 5.1报错:No supported encrypter found的办法
Jun 07 PHP
PHP查找与搜索数组元素方法总结
Jun 12 #PHP
php使用array_search函数实现数组查找的方法
Jun 12 #PHP
php线性表的入栈与出栈实例分析
Jun 12 #PHP
php数组合并与拆分实例分析
Jun 12 #PHP
php结合ACCESS的跨库查询功能
Jun 12 #PHP
php中smarty实现多模版网站的方法
Jun 11 #PHP
php中smarty模板条件判断用法实例
Jun 11 #PHP
You might like
人大复印资料处理程序_补充篇
2006/10/09 PHP
Zend Studio 无法启动的问题解决方法
2008/12/04 PHP
php空间不支持socket但支持curl时recaptcha的用法
2011/11/07 PHP
php使用exec shell命令注入的方法讲解
2013/11/12 PHP
PHP仿tp实现mvc框架基本设计思路与实现方法分析
2018/05/23 PHP
JavaScript具有类似Lambda表达式编程能力的代码(改进版)
2010/09/14 Javascript
改善用户体验的五款jQuery插件分享
2011/05/22 Javascript
读jQuery之一(对象的组成)
2011/06/11 Javascript
javascript 进阶篇3 Ajax 、JSON、 Prototype介绍
2012/03/14 Javascript
点击弹出层外区域关闭弹出层jquery特效示例
2013/08/25 Javascript
jquery动态改变form属性提交表单
2014/06/03 Javascript
jQuery中trigger()方法用法实例
2015/01/19 Javascript
jQuery绑定事件的四种方式介绍
2016/10/31 Javascript
jquery 键盘事件的使用方法详解
2017/09/13 jQuery
vue路由前进后退动画效果的实现代码
2018/12/10 Javascript
微信小游戏中three.js离屏画布的示例代码
2020/10/12 Javascript
[04:49]2014DOTA2国际邀请赛 Newbee顺利挺进总决赛 ImbaTV独家专访
2014/07/19 DOTA
浅谈python中np.array的shape( ,)与( ,1)的区别
2018/06/04 Python
Python实现八皇后问题示例代码
2018/12/09 Python
python打开使用的方法
2019/09/30 Python
CSS3 倾斜的网页图片库实例教程
2009/11/14 HTML / CSS
Space NK英国站:英国热门美妆网站
2017/12/11 全球购物
Canal官网:巴西女性时尚品牌
2019/10/16 全球购物
用C#语言写出在本地创建一个UDP接收端口的具体过程
2016/02/22 面试题
优秀经理事迹材料
2014/02/01 职场文书
会计专业自我评价
2014/02/12 职场文书
企业年度评优方案
2014/06/02 职场文书
企业宣传标语
2014/06/09 职场文书
设计专业毕业生求职信
2014/06/25 职场文书
工作总结与自我评价
2014/09/18 职场文书
学校党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
2015教师见习期工作总结
2014/12/12 职场文书
2015年学习部工作总结范文
2015/03/31 职场文书
门球健将观后感
2015/06/16 职场文书
解决Maven项目中 Invalid bound statement 无效的绑定问题
2021/06/15 Java/Android
Python利用capstone实现反汇编
2022/04/06 Python