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 相关文章推荐
Search Engine Friendly的URL设计
Oct 09 PHP
用Zend Encode编写开发PHP程序
Oct 09 PHP
10 个经典PHP函数
Oct 17 PHP
有关于PHP中常见数据类型的汇总分享
Jan 06 PHP
php.ini save_handler 修改不生效的解决办法
Jul 22 PHP
Thinkphp多文件上传实现方法
Oct 31 PHP
php将access数据库转换到mysql数据库的方法
Dec 24 PHP
php实现微信公众号无限群发
Oct 11 PHP
PHP结合jQuery插件ajaxFileUpload实现异步上传文件实例
Aug 17 PHP
PHP+Ajax实现无刷新分页实例详解(附demo源码下载)
Apr 07 PHP
laravel如何开启跨域功能示例详解
Aug 31 PHP
解决Laravel5.5下的toArray问题
Oct 15 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
基于MySQL分区性能的详细介绍
2013/05/02 PHP
获取php页面执行时间,数据库读写次数,函数调用次数等(THINKphp)
2013/06/03 PHP
Laravel框架学习笔记(一)环境搭建
2014/10/15 PHP
PHP网站开发中常用的8个小技巧
2015/02/13 PHP
帝国cms目录结构分享
2015/07/06 PHP
PHP下使用mysqli的函数连接mysql出现warning: mysqli::real_connect(): (hy000/1040): ...
2016/02/14 PHP
php判断用户是否关注微信公众号
2016/07/22 PHP
PHP序列化和反序列化深度剖析实例讲解
2020/12/29 PHP
javascript实现下拉提示选择框
2015/12/29 Javascript
分享有关jQuery中animate、slide、fade等动画的连续触发、滞后反复执行的bug
2016/01/10 Javascript
AngularJS整合Springmvc、Spring、Mybatis搭建开发环境
2016/02/25 Javascript
JS检测移动端横竖屏的代码
2016/05/30 Javascript
D3.js实现饼状图的方法详解
2016/09/21 Javascript
JS百度地图搜索悬浮窗功能
2017/01/12 Javascript
Node.js使用Koa搭建 基础项目
2018/01/08 Javascript
如何用webpack4带你实现一个vue的打包的项目
2018/06/20 Javascript
JavaScript实现学生在线做题计时器功能
2018/12/05 Javascript
Python struct.unpack
2008/09/06 Python
探究Python中isalnum()方法的使用
2015/05/18 Python
Python面向对象编程之继承与多态详解
2018/01/16 Python
利用pandas将numpy数组导出生成excel的实例
2018/06/14 Python
对Django中的权限和分组管理实例讲解
2019/08/16 Python
Python属性和内建属性实例解析
2020/01/14 Python
Python pysnmp使用方法及代码实例
2020/08/24 Python
HTML5 WebGL 实现民航客机飞行监控系统
2019/07/25 HTML / CSS
伦敦的高级牛仔布专家:Trilogy
2018/08/06 全球购物
客服专员岗位职责范本
2013/11/29 职场文书
安全教育月活动总结
2014/05/05 职场文书
公司承诺书格式
2014/05/21 职场文书
金融专业求职信
2014/08/05 职场文书
公司离职证明标准范本
2014/10/05 职场文书
预备党员考察表党小组意见
2015/06/01 职场文书
初中军训感言
2015/08/01 职场文书
大学生干部培训心得体会
2016/01/06 职场文书
2016教师党员学习心得体会
2016/01/21 职场文书
Mac环境Nginx配置和访问本地静态资源的实现
2021/03/31 Servers