19

当我遇到一个奇怪的情况时,我正在用 PHP 编写一个 Web 应用程序。为了说明我的问题,考虑一个这种结构的网络应用程序:

/
    index.php
    f1/
        f1.php
    f2/
        f2.php

这些文件的内容:

索引.php:

<?php require_once("f1/f1.php"); ?>

f1.php:

<?php require_once("../f2/f2.php"); ?>

f2.php:空白

现在,当我尝试在浏览器中打开 index.php 时,出现此错误:

Warning: require_once(../f2/f2.php) [function.require-once]: 
failed to open stream: No such file or directory in /var/www/reqtest/f1/f1.php on line 2
Fatal error: require_once() [function.require]: 
Failed opening required '../f2/f2.php' (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/reqtest/f1/f1.php on line 2

我有什么明显的遗漏吗?包含路径如何在 PHP 中工作?


在我问这个问题之前,我尝试过尝试并找出答案。我设置了另一个测试,如下所示:

/
    index.php
    f1/
        f1.php
        f2.php

索引.php:

<?php require_once("f1/f1.php"); ?>

f1.php:

<?php require_once("f2.php"); ?>

f2.php:空白

令我惊讶(和完全混乱),这很好!

那么,路径解析背后的秘密是什么?

PS我看到了这个问题,但它仍然没有回答我在这里所说的第二种情况。

4

5 回答 5

12

如果包含另一个文件,则工作目录将保留在包含文件所在的位置。

您的示例按预期工作。

编辑:第二个示例有效,因为 . (实际目录)在您的包含路径中(请参阅您的错误消息)。

Edit2: 在您的第二个示例中,您感兴趣的关键点是这一行:

<?php require_once("f2.php"); ?>

起初它会在当前工作目录 ( /var/www/req_path_test) 中查找,但没有找到 f2.php。

作为后备,它将尝试在您的 include_path ( '.:/usr/share/php:/usr/share/pear') 中查找 f2.php,以 '.' 开头 (这是相对于实际文件,而不是包括一个)。

所以 './f2.php' 有效,并且 require 不会失败。

于 2009-12-29T10:23:13.137 回答
4

当您打开 index.php 时,工作目录被设置为该文件所在的文件夹。在插入的 f1.php 中,这个工作目录不会改变。

您可以使用相对于当前包含文件的绝对路径来包含文件,如下所示:

require_once(dirname(__FILE__).'/../../test/file.php')

但如果这些文件包含类,最好考虑使用自动加载器。

于 2009-12-29T10:15:09.250 回答
0

通常在你的旧结构中

<?php require_once("f2/f2.php"); ?>

代替

<?php require_once("../f2/f2.php"); ?>

应该管用。据我所知php从初始脚本中获取路径

于 2009-12-29T10:04:50.080 回答
0

听起来您的服务器在 PHP 配置中启用了open_basedir设置。这使得无法在目录结构中包含(和打开)您上方的文件夹中的文件(即,您不能使用 ../ 在文件夹结构中上升)。

于 2009-12-29T10:21:23.307 回答
0

来自 PHP Docs PHP 包括

根据给定的文件路径包含文件,如果没有给出,则根据指定的 include_path 包含文件。如果在 include_path 中找不到该文件,则 include 最终会在失败之前检查调用脚本自己的目录和当前工作目录。

如果没有给出文件路径,即 require_once("f2.php");

第一个。检查 include_path

第二。检查调用脚本自己的目录

第三。最后检查当前工作目录

如果找不到文件,则 PHP 会在文件包含时抛出警告,并在需要时抛出致命错误

如果定义了路径——无论是绝对路径(在 Windows 上以驱动器号或 \ 开头,或在 Unix/Linux 系统上以 / 开头)还是相对于当前目录(以 . 或 .. 开头)—— include_path 将被完全忽略。例如,如果文件名以 ../ 开头,解析器将在父目录中查找请求的文件。

如果您包含/要求您的文件以 . 或 .. 或 ./ 然后 PHP 的解析器将在当前工作目录的父目录中查找,即 require_once("../f2/f2.php"),php 将在根目录中查找调用脚本 index.php在那个目录下。

现在您还没有在 PHP 脚本中定义任何包含路径,因此它总是回退到调用脚本,然后进入当前工作目录。

// Check your default include path, most likely to be C:\xampp\php\PEAR
echo get_include_path();

// To set include path
set_include_path ( string $new_include_path ) : string

当前工作目录源自您的主要调用脚本 index.php。

// The Current Working Directory can be checked
echo getcwd();

在第一个示例中,所需文件“../f2/f2.php”来自 f1.php

您的代码不起作用,因为-

  1. PHP 会忽略指定的路径,因为您的文件名以 ../ 开头
  2. f1/ 调用脚本自己的目录也被忽略。
  3. 解析器目录查找父目录以查找请求的文件。当前工作目录是根目录,这是您启动工作脚本 index.php 的位置。该文件不在此目录中,给出的路径错误。

因此你得到致命错误

在第二个示例中,您已将目录 & 从 f1.php 更改为 require_once("f2.php")。

您的代码有效,因为 -

  1. 这一次你 require("f2.php") 没有前导 ../ 或 ./ 这一次 PHP 检查 include_path 但确实在那里找到它,因为你没有定义它并且文件不在默认预设 include_path 中。
  2. 这次调用脚本 f1.php 的目录是 f1/。并且您需要的文件(“f2.php”)位于此目录中。PHP 这次检查这个目录下的文件并找到它。
  3. PHP 不必在找到文件时检查工作目录。

因此您的代码工作正常!

于 2019-02-27T02:34:16.867 回答