2009-12-29 47 views
15

當我遇到一種奇怪的情況時,我正在用PHP編寫一個web應用程序。爲了說明我的問題,可以考慮這種結構的Web應用程序:這些文件的如何在require_once中包含路徑解析工作?

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

內容:

的index.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 

的index.php:

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

f1.php:

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

f2.php:空白

令我驚訝(並且完全混淆),這樣做很好!

那麼,路徑分辨率背後的祕密是什麼?

PS我看到this question,但它仍然沒有回答我在這裏陳述的第二種情況。

+0

我已經繞過這個問題(使用dirname)。我想知道的是爲什麼第二個案例不會失敗。它是一個錯誤還是一個功能? – jrharshath 2009-12-29 10:19:53

+0

編輯我的答案覆蓋第二個例子。 – Karsten 2009-12-29 10:29:10

+0

我找不到手冊頁,它記錄了從f1.php成功調用require_once('f2.php')的過程。 Docs表示,如果沒有提供路徑信息,include_path會被忽略(不管怎麼說,從include_path中刪除'。'都沒有效果),getcwd()表明include目錄周圍的工作目錄是相同的。嚴重的是,它看起來像一個無證的功能。 – 2009-12-29 11:37:17

回答

10

如果包含其他文件,則工作目錄將保留在包含文件所在的位置。

您的示例正按預期工作。

編輯:第二個例子是有效的,因爲。 (實際目錄)位於包含路徑中(請參閱錯誤消息)。

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'起作用,並且要求不會失敗。

+0

我試過echo:ing index.php和f1.php中的getcwd()。這兩個地方的輸出都是'/ var/www/req_path_test' 所以「。」在包含路徑中可能意味着「/ var/www/req_path_test」位於包含路徑中。 – jrharshath 2009-12-29 10:47:39

+0

爲了支持這個事實,我嘗試了'require_once(「f2/f2.php」)'。它在我打開index.php時工作,但不是當我打開f1/f1.php時。 – jrharshath 2009-12-29 10:51:21

+0

我更新了我的回答以涵蓋您的評論。 – Karsten 2009-12-29 11:01:36

0

Normaly在你的舊體制

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

,而不是

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

應該工作。據我所知php從最初的腳本中獲取路徑

+0

我知道。我真正想知道的是爲什麼第二種情況不是失敗。它不是一個問題,它的癢:) – jrharshath 2009-12-29 10:16:39

4

當您打開index.php時,工作目錄設置爲此文件所在的文件夾。而在insluded f1.php中,此工作目錄不會更改。

您可以通過使用他們的絕對路徑包括文件,相對於當前包含的文件是這樣的:

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

但最好考慮使用自動加載磁帶機,如果這些文件包含的類。

+0

第二種情況呢?爲什麼這個工作? – jrharshath 2009-12-29 10:17:18

+0

嘗試添加'echo getcwd();'看你的腳本,看看當前的工作目錄是如何改變的。 http://php.net/manual/en/function.getcwd.php - 這裏的評論說,它的行爲從PHP4變爲PHP5爲例。 – 2009-12-29 10:25:10

0

聽起來您的服務器在PHP配置中啓用了open_basedir設置。這使得無法在目錄結構中的文件夾中包含(並打開)文件(即,不能使用../在文件夾結構中)。

+0

在我的服務器上,open_basedir設置有「沒有價值」。那是什麼意思? – jrharshath 2009-12-29 10:23:58

+0

no value = disabled – Karsten 2009-12-29 10:30:10

+0

@Karsten這意味着「../」被允許,對吧? – jrharshath 2009-12-29 10:42:16