【问题标题】:PHP: Why such weird behaviour when I include a file from another directory which also includes a file?PHP:当我从另一个目录中包含一个文件时,为什么会出现这种奇怪的行为?
【发布时间】:2011-03-07 04:12:09
【问题描述】:

我从来没有见过这样的事情。

文件结构:

  • somefolder/base.php
  • 包括/stuff.php
  • 包括/constants.php

base.php:

<?php require("../includes/stuff.php"); ?>

stuff.php:

<?php 
   require("constants.php"); 
   echo "Welcome to stuff.php";
?>

constants.php:

<?php echo "IMPORTANT CONSTANTS DEFINED HERE!";  ?>

结果:

欢迎使用 stuff.php

为什么不显示 constant.php 消息?!我会告诉你什么不是问题:它不是 php 代码。

我从一些复杂的文件开始,其中常量文件实际上是 DEFINE()-ing 一些常量,并且由于某种原因,只有前几个常量在工作。我最终禁用了包括 DEFINE() 在内的所有无关代码,并且只使用了 echo 语句,而这个问题仍然让我眼前一亮。顺便说一句,无论代码的顺序如何,一些已定义的常量如何通过而不是任何回声?

所以我终于意识到这很荒谬,并决定创建一些新文件作为测试。那些工作。或者他们没有,我忘记了。无论如何,通过创建新文件并尝试移动它们并将代码从一个文件复制到另一个文件,我已经取得了一定的成功,但似乎没有任何押韵或理由。

哇,这只是在:我让 constants.php 文件以不同的名称工作,但是当我将其更改为 constants.php 时它停止工作!我尝试在不同的浏览器中清除缓存/打开并重新启动服务器,但没有任何帮助。我觉得我或我的电脑吸毒了。啊啊啊!!!


编辑

啊哈。我遗漏了一条看起来很重要的信息。一个我没有提到的文件。

  • somefolder/constants.php

包含该文件而不是包含/constants.php。这就是为什么我没有收到任何丢失文件错误的原因。那是完全令人困惑的事情!我希望子包含在更高级别包含之前发生,所以 stuff.php 会在它自己的目录中查找 constants.php 但我猜 base.php 包含 stuff.php 并且 base.php 会包含在 stuff.php 中指定的内容,这意味着包含相对于 base.php。所以绝对路径毕竟是解决方案。

其他编辑:

非常有趣。当我简单地更改includes/constants.php 的名称(例如更改为constanza.php)之前,我仍然很困惑为什么它会起作用。看起来文件包含并没有那么简单。如果有两个同名的文件,它会优先选择一个相对于执行包含的父文件的文件。但如果它别无选择,它会相对于孩子去做就好了。

【问题讨论】:

  • 通过设置 error_reporting 和 display_errors 启用错误报告。
  • 我已经让它显示警告和错误,但我添加了 到每个文件的顶部只是为了查看。没有不同。但报告确实有效。如果我使用完整的原始常量.php,当我尝试从基本文件中回显常量时,它会抱怨“注意:使用未定义的常量 TBL_USERS”。
  • @Moss,我刚试过你的方案,它有效??!也许他们修复了它,我使用的是 PHP 5.6。

标签: php include nested path


【解决方案1】:

包含中使用的路径与包含的文件无关:它们与include_path 相关。

这意味着使用包含/要求的相对路径通常不会像您期望的那样......


通常使用的解决方案是使用绝对路径;这样,您就可以确定包含哪些内容。

当然,在您的代码中使用绝对路径是不好的(当您的应用程序部署到另一个路径时,它将在一台服务器上工作,但在另一台服务器上工作);所以,解决办法是:

  • 获取您所在文件的绝对路径
  • 除了指向另一个文件的相对路径之外,还可以使用它来包含该文件。


可以使用__FILE__ 获取您所在文件的完整路径。

表示当前文件的目录(指令写入的文件)可以通过dirname(__FILE__)获取。

之后,只需编写正确的路径即可。
例如,在stuff.php 中,您会使用:

require(dirname(__FILE__) . "/constants.php"); 

而在 base.php 中,您会使用:

require(dirname(__FILE__) . "/../includes/stuff.php");

【讨论】:

  • dirname(dirname(__FILE__)) 将为您提供父目录。我倾向于只存储应用程序的基本目录,然后使用相对于该目录的路径。
  • 这听起来很合理也很好,但只要文件不命名为 constant.php,我就已经可以正常工作了。这些文件被很好地包含在内。没有关于丢失文件的错误。我试过你的建议,我之前也用过 $_SERVER['DOCUMENT_ROOT'] 。两者都没有区别。
  • 对不起。你是对的。我没有在 base.php 上尝试所有内容的绝对路径。请参阅我对原始问题的编辑说明。我想我需要休息一晚才能理解这一点。顺便说一句,使用 PHP 5.3.0 __DIR__ 将是执行您建议的最简单方法。
  • @Pascal Martin,为什么不用__DIR__ 而不是dirname(__FILE__)
【解决方案2】:

我发现有帮助的是检查getcwd()(获取当前工作目录),这将返回包含它的文件的文件夹路径。如果包含文件在我的顶层目录下(下一层)被调用,那么我可以计算并预先添加适当数量的../s。

即,如果我知道我的包含文件在 topfolder/css/blah.css 中,那么我可以像这样检查包含文件中 getcwd() 的值:

$leaveDirectoryIfNecessary = "";
// Grab the last 9 characters of the directory name
if (substr(getcwd(), -9) != "topfolder") {
    $leaveDirectoryIfNecessary = "../";
}

然后我会在我在包含文件中引用的每个文件之前echo $leaveDirectoryIfNecessary,如下所示:

<link rel="stylesheet" type="text/css" href="<?php echo $leaveDirectoryIfNecessary; ?>css/goodstuff.css">

值得注意的是,这假定您不会在子文件夹树中的任何位置重复父/顶级文件夹的名称。

如果您碰巧有更深的文件夹结构超出包含包含文件的一级深度,则您还需要进行某种循环并计算“topfolder”之后当前工作目录中的正斜杠数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-27
    • 2010-10-30
    • 2015-11-26
    相关资源
    最近更新 更多