php 包含路径解析如何在 require_once 中工作?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1973813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 04:31:08  来源:igfitidea点击:

How does include path resolution work in require_once?

phpincludeinclude-pathrequire-once

提问by jrharshath

I was writing an web app in PHP, when I encountered a strange situation. To illustrate my problem, consider a web app of this structure:

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

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

Contents of these files:

这些文件的内容:

index.php:

索引.php:

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

f1.php:

f1.php:

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

f2.php: blank

f2.php:空白

now when I try to open index.php in my browser I get this error:

现在,当我尝试在浏览器中打开 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

Is there something obvious I'm missing? how do include paths work in PHP?

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



Before I asked this question, I attempted to experiment and find out. I set up another test, like so:

在我问这个问题之前,我试图进行实验并找出答案。我设置了另一个测试,如下所示:

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

index.php:

索引.php:

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

f1.php:

f1.php:

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

f2.php: blank

f2.php:空白

To my surprise (and utter confusion), this worked out fine!

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

So, what is the secret behind the path resolution?

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

PS I saw this question, but it still does not answer the second case that I've stated here.

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

采纳答案by Karsten

If you include another file, the working directory remains where the including file is.

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

Your examples are working as intended.

您的示例按预期工作。

Edit:The second example works because . (actual directory) is in your include path (see your error message).

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

Edit2:In your second example, the key point of your interest is this line:

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

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

At first it will look in the current working dir (/var/www/req_path_test), but does not find f2.php.

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

As fallback, it will try to find f2.php in your include_path ('.:/usr/share/php:/usr/share/pear'), starting with '.' (which is relative to the actualfile, not the includingone).

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

So './f2.php' works and the require does not fail.

所以 './f2.php' 可以工作并且 require 不会失败。

回答by Vladislav Rastrusny

When you open index.php, working dir is set to the folder this file resides in. And inside insluded f1.php this working dir does not change.

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

You can include files by using their absolute paths, relative to the current included file like this:

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

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

But better consider using an autoloader if these files contain classes.

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

回答by Emil Vikstr?m

It sounds like your server has the open_basedirsetting enabled in the PHP configuration. This makes it impossible to include (and open) files in folders above your in the directory structur (i.e., you can't use ../ to go up in the folder structure).

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

回答by user207675

Normaly in you old structure

通常在你的旧结构中

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

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

instead of

代替

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

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

should work. As far as i know php takes the paths from the initial script

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

回答by Mohammad Daud Ibrahim

From the PHP Docs PHP include

来自 PHP Docs PHP 包括

Files are included based on the file path given or, if none is given, the include_path specified. If the file isn't found in the include_path, include will finally check in the calling script's own directory and the current working directory before failing.

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

If the file path is not given then i.e require_once("f2.php");

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

1st. The include_path is checked

第一。include_path 被检查

2nd. The calling scripts own directory is checked

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

3rd. Finally the current working directory is checked

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

If file not found then PHP throws warning on file include & fatal error on require

如果未找到文件,则 PHP 会在文件包含和需要的致命错误上抛出警告

If a path is defined — whether absolute (starting with a drive letter or \ on Windows, or / on Unix/Linux systems) or relative to the current directory (starting with . or ..) — the include_path will be ignored altogether. For example, if a filename begins with ../, the parser will look in the parent directory to find the requested file.

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

If you include/require your file beginning with . or .. or ./ then PHP's parser will look in the parent directory which is the current working directory i.e require_once("../f2/f2.php"), php will check at the root directory as the calling script index.php is in that directory.

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

Now You have not defined any include path in your PHP script thus it always falls back to the calling script and then into the current working directory.

现在您还没有在 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

The Current Working Directory is derived from your main calling script index.php.

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

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

In the first Example where the required file "../f2/f2.php" is from f1.php

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

You code does not work because -

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

  1. The specified path is ignored by PHP as your filename begins with ../
  2. f1/ the calling script's own directory is ignored as well.
  3. The parser directory looks into the parent directory to find the requested file. The current working directory is root directory, this is from where you have initiated the working script index.php. The file is not located at this directory, wrong path given.
  1. PHP 会忽略指定的路径,因为您的文件名以 ../
  2. f1/ 调用脚本自己的目录也被忽略。
  3. 解析器目录查看父目录以查找请求的文件。当前工作目录是根目录,这是您启动工作脚本 index.php 的地方。该文件不在此目录中,给出了错误的路径。

Thus you get the Fatal Error

因此你得到了致命错误

In the Second example you have changed the directory & from f1.php you require_once("f2.php").

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

Your code works because -

您的代码有效,因为 -

  1. This time you require("f2.php") no leading ../ or ./ This time PHP checks the include_path but does find it there, as you haven't defined it and the file does not reside in the default preset include_path.
  2. This time the calling script f1.php's directory is f1/. and you require file ("f2.php") is located at this directory. PHP This time checks the file in this directory and finds it.
  3. PHP does not have to check the working directory as the file was found.
  1. 这次您需要("f2.php") 没有前导../ 或./ 这次PHP 检查include_path 但确实在那里找到了它,因为您还没有定义它并且该文件不在默认预设include_path 中。
  2. 这次调用脚本f1.php的目录是f1/。并且您需要的文件(“f2.php”)位于此目录中。PHP 这次检查这个目录下的文件,找到了。
  3. PHP 不必在找到文件时检查工作目录。

Thus Your Code Works Fine!

因此您的代码工作正常!