include_once和相对路径在PHP中的使用

10

我有三个文件: home, failed_attempt, login.

home和failed_attempt都引用了login文件。

让人烦恼的是,它们都会抛出一个错误,说login文件不存在。如果这样做,home将会抛出异常,但failed_attempt不会。

  include_once("../StoredProcedure/connect.php");

include_once("../untitled/sanitize_string.php");

如果我这样做:

   include_once("StoredProcedure/connect.php");
   include_once("untitled/sanitize_string.php");

相反的情况发生了,failed_attempt会抛出异常,但是home不会。我该如何解决这个问题。

我是否应该通过添加../来让include去上一页,因此home.php不需要上一页,因此它会抛出异常。

我如何使两个文件都接受那些包含作为有效的..可能不是相对于它们放置的位置..即,没有那个../

目录结构:

PoliticalForum
->home.php
->StoredProcedure/connect.php
->untitled/sanitize_string.php
->And other irrelevant files

1
你的问题不是很明确。home、failed_attempt和login文件是否在同一目录下?你能发布一下你的目录结构吗?home和failed_attempt页面如何“引用”登录文件?以上代码出现在哪个文件中? - daiscog
storedProcedure是我的文件夹,里面有文件。按照要求的一切...登录文件中有2个包含它们的内容无法加载,这取决于您从哪里调用它们...主页或位于不同目录中的login_attempt页面。 - Matrix001
5个回答

11

在PHP中,像realpath()__DIR__这样的东西是你创建路径时的好帮手。

Realpath http://php.net/manual/en/function.realpath.php

Magic constants http://php.net/manual/en/language.constants.predefined.php

由于includerequire是语言结构(而不是函数),因此它们不需要括号。一般来说,你会使用include来包含“模板”(输出文件),而使用require来包含例如类的PHP文件。

因此,你可以使用以下代码:

$sPath = realpath( __DIR__ . '/../relative/path/here');
if($sPath) { require_once $sPath; }

(在 PHP < 5 中使用 dirname(__FILE__) 替代 __DIR__)

在尝试 require 文件之前,值得评估路径,因为如果文件不存在,realpath() 返回 false,并且尝试 require false; 会导致 PHP 错误。

或者您可以使用绝对路径,例如:

require /home/www/mysite.com/htdocs/inc/somefile.php


这个也不行:include_once(realpath("../untitled/sanitize_string.php")); - Matrix001
它确实消除了错误。但是如果realpath返回false呢?这不意味着文件不会被包含吗?realpath什么时候会返回false? - Matrix001
如果realpath()函数的参数所输入的路径不存在,例如realpath('this/file/does/not/exist');将返回false。如果该文件确实存在,则会返回给定文件的真实路径,因此realpath(__DIR__ . '/this/file/does/exist');可能会返回类似于/home/mysite.com/htdocs/this/file/does/exist的内容,即完整的实际路径。 - CD001
我在__autoload函数中使用了try和catch。我别无选择,也不知道如何解决这个冲突。为什么绝对路径行不通呢?比如这样PoliticalForum/untitled..为什么不能让这个路径适用于所有文件,无论它们是什么类型的文件。我讨厌相对路径。 - Matrix001
另一种解决方法可能是将所有的包含文件放在一个文件夹中,并使用类似于 set_include_path() 的函数将其设置为“包含路径”(当然还有其他方法)... http://php.net/manual/zh/function.set-include-path.php - CD001
嗯...听起来很有趣。但是每次引用那个文件时,再次包含所有这些文件会不会有点繁琐呢?但仍然存在一个问题...因为如果我将文件放在文件夹中,这意味着我必须这样做 ../../relativepath.php,而对于其他文件,我需要这样做 ../relativepath.php,对于在主目录或从中调用include的相同目录中的文件,我需要这样做 relativepath.php。所以相对路径是一个垃圾发明。有没有替代方法? - Matrix001

9
这里有三种可能的解决方案。第二种方法只是巧妙地使用绝对路径的变通方法。
1:进入正确的目录chdir
<?php

// check if the 'StoredProcedure' folder exists in the current directory
// while it doesn't exist in the current directory, move current 
// directory up one level.
//
// This while loop will keep moving up the directory tree until the
// current directory contains the 'StoredProcedure' folder.
//
while (! file_exists('StoredProcedure') )
    chdir('..');

include_once "StoredProcedure/connect.php";
// ...
?>

请注意,只有当您的存储过程文件夹位于可能需要包含其中文件的任何文件的最顶层目录中时,才能使用此方法。
2:使用绝对路径
在您试图实现它之前,请注意这并不是可移植的,它实际上取决于您如何实现它。以下是一个在Apache中有效的示例:
<?php
include_once $_SERVER['DOCUMENT_ROOT'] . "/StoredProcedure/connect.php";
// ...
?>

或者,使用Apache,在根目录的.htaccess文件中添加以下内容:

php_value auto_prepend_file /path/to/example.php

那么在example.php中:

<?php

define('MY_DOC_ROOT', '/path/to/docroot');

?>

最后,在您的文件中:


<?php
include_once MY_DOC_ROOT . "/StoredProcedure/connect.php";
// ...
?>

3:设置PHP的include_path

请参阅include_path指令的手册条目。如果您无法访问php.ini,则可以在.htaccess中设置此项,前提是您正在使用Apache且PHP未安装为CGI,如下所示:

php_value include_path '/path/to/my/includes/folder:/path/to/another/includes/folder'

我对第一种方法的工作方式有点模糊,但我会尝试第二种和第三种方法。 - Matrix001
我已经在第一个方法中添加了注释。更多信息请参见chdir手册页面 - daiscog

6

对于初学者,这将有助于理解。根据您的相对路径,简单使用以下内容:

//include file directly from parent directory:
include_once(dirname(__FILE__) . '/../connect.php');

或者

//include file from parent's child directory:
include_once(dirname(__FILE__) . '/../StoredProcedure/connect.php');

或者

//include file from own child directory:
include_once('StoredProcedure/connect.php');

或者

//include sibling files from same directory:
include_once('connect.php');

1
我的情况是第二种情况,这对我起作用了。 - Macarrao

2

要做类似于require(dirname(__FILE__) . '[RELATIVE PATH HERE]');的事情。


你的意思是像这样吗: [code]include_once(dirname(FILE) . "../StoredProcedure/connect.php"); include_once(dirname(FILE) ."../untitled/sanitize_string.php"); .. 它不起作用[/code] - Matrix001
dirname(FILE)会返回包含include代码的文件所在的当前目录,只需将相对路径附加到该文件即可。为了方便起见,您可以打印dirname(FILE)的值并查看发生了什么。 - Riz
但它的工作不太对:include_once(dirname(FILE)."../StoredProcedure/User/login.php"); 当我包括登录时会出现问题...你的代码行不起作用。 - Matrix001
请查看问题下面'daiscog'的评论,并写出问题中的目录结构。 - Riz
更新:DIR 是否会给我当前所在的目录?如果我在我的网站中的“untitled”目录中,而home.php在主目录中,那么在相对路径之前放置目录名称有什么帮助呢? - Matrix001

1
其他人已经正确回答了你的问题,但是我想再贡献一些东西:自动加载器。
自动加载器允许你定义一个函数,在你尝试使用一个类时自动包含某些文件。
文档在这里,可以比我更好地解释它:http://php.net/manual/en/language.oop5.autoload.php 真的建议使用它们,会节省你的时间并且是更好的实践。

我知道它们...当你开始页面时,文件被加载...你把你的包含在其中...但这并不能解决我的问题,对吧? - Matrix001

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接