网站推广.NET

网站推广.NET

PHP关于require_once路径问题的详解

来源:互联网

我的站点目录如下:

**************************************************************

wwwroot   //网站根目录 绝对路径为: F:/wwwroot

-- folder_a // 文件夹A

 file_a_a.php   file_a_b.php   file_a_c.php

-- folder_b // 文件夹B

立即学习“PHP免费学习笔记(深入)”;

file_b_a.php   file_b_b.php   file_b_c.php

-- index.php

*************************************************************

这个目录层次已经很清楚了:

wwwroot为根目录,下面有index.php文件和folder_a,folder_b两个文件夹

这两个文件夹分别有3个php文件

先来看index.php文件的内容:

<?php     require_once("folder_a/file_a_a.php");     echo "文件folder_a_a.php被包含成功";?>

再来看folder_a/folder_a_a.php文件的内容:

<?php     require_once("../folder_b/file_b_a.php");     $x = new X();     $x.printInfo();?>

最后再来看看folder_b/folder_b_a.php文件的内容:

<?php     class X{          function printInfo(){               echo &#39;success;          }     }?>

ok 如果我现在直接运行 floder_a/file_a_a.php

那么会输出: success

如果我运行 wwwroot下的index.php

那么会报错,原因是找不到包含文件:file_b_a.php

但是如果我在所有的require_once()中加入 dirname(FILE).'/'

那么无论运行 file_a_a.php 还是 index.php 都可以正常输出

*********************************************************

问题:

我第一次使用的是相对路径,所以重复包含的时候就出错了

而我第二次使用的是绝对路径,所以不出错.可是我还是有点疑惑:

我先分析了以下使用相对路径会出错的原因:

我运行index.php,它能找到 folder_a目录,也能找到该目录下的file_a_a.php,于是它就把 folder_a/file_a_a.php 里的内容复制到了index.php 的第一行(包含语句的那行),然后再继续运行(也就是运行包含过来的内容),因此此时等于是在index.php中运行 file_a_a.php 中的require_once('../folder_b/file_b_a.php'); 它根据当前index.php的位置去找这个路径文件(file_b_a.php),当然找不到啦,所以它出错了.

可是我使用绝对路径的时候不是一样的道理吗?可为什么它就不出错?可能这句话大家有点不解了,我来详细说明(根据程序的运行顺序来说明).

程序先运行 index.php(注意此时我加上了 dirname(FILE),所以当前是绝对路径),

index.php先运行第一句代码:require_once(dirname(FILE).'/'.'folder_a/file_a_a.php');

dirname(FILE) 就是 f:/wwwroot/ 所以这句代码包含的路径也就是:

f:/wwwroot/folder_a/file_a_a.php

这个路径是正确的,因此没问题是吧

ok 第一步正确完成

然后它就把 file_a_a.php 中的代码复制到的 index.php 的这个地方:

然后仍然继续运行: 这是也就是在index.php 中运行file_a_a.php 中的所有代码,那么我们来看看它运行那些代码?

<?php     require_once(dirname(FILE).&#39;/&#39;."../folder_b/file_b_a.php");     $x = new X();     $x.printInfo();?>

对就是这些,需要注意的是,这些代码已经被复制到了index.php,也就是说,现在index.php的内容实际上就变成了:

<?php     require_once(dirname(FILE).&#39;/&#39;."../folder_b/file_b_a.php");     $x = new X();     $x.printInfo();     echo "文件folder_a_a.php被包含成功";?>

那么仍然按程序的执行顺序来分析以上代码:

dirname(FILE) 应该是 f:/wwwroot (因为现在这些代码在index.php中执行,和相对路径一样的道理,因此得到的是index.php所在的目录)

那么包含的路径应该就是: f:/wwwroot/../folder_b/file_b_a.php

那么我们检查下这个路径是否有file_b_a.php文件呢? 答案是没有,因为 f:/wwwroot/../folder_b 已经返回到的f:盘符下的folder_b目录,而这个目录并不存在.

但是执行的结果却让我不解,它竟然正确输出了.

也许大家会说:在相对路径中,index.php 先包含了 file_a_a.php 然后再执行包含 file_b_a.php 的代码,所以找不到目录.而使用绝对路径后,index.php 在包含 file_a_a.php 之前,file_a_a.php 已经先执行了包含 file_b_a.php 的代码,所以正确输出.但是请注意:php文档中以及许多文档教程都是这样说明的:包含一个文件,实际上就是将被包含的文件中的代码复制到包含命令的地方,就算这个观点是错误的,那么同样是 require_once 命令,不可能对相对路径就是先包含再执行,而对绝对路径却是先执行再包含吧.

不解,请大家指教.(非常感谢大家能看到这里,问题很长,是因为我郁闷的时间更长,所以请大家不要 Ctrl+C Ctrl+V,也不要说:看 API 或 自己找资历 等等了.)谢谢.

不要想得太复杂...

用绝对路径:

你的c:\a.php

可以引用

d:\b.php

你理解错的一点就是 FILE永远指向当前文件,无论是主执行文件,还是被包含文件

也就是说: 如果是使用相对路径 ../folder_b/file_b_a.php 那么会先复制过来,然后在指向地址,如果使用FILE,就会先指向,然后再被包含,是这样吗?

如果用的是虚拟目录 那这个目录就会以你当前运行的文件为基准

也就是

folder_a/folder_a_a.php文件的内容这样写:

<?php     require_once("folder_b/file_b_a.php");     $x = new X();     $x.printInfo();?>

你看下会不会错

在跟目录里建个文件,把要引用的文件全部按绝对路经引进来;其他目录引这个文件就好了.

require_once