[英]Setting the path for include / require files
我所有的PHP包含文件都在一個目錄中:
https://www.mywebsite.com/includes
在頂級頁面中插入這些文件非常簡單:
<?php include 'includes/logo.php'; ?>
<?php include 'includes/main_nav.php'; ?>
<?php include 'includes/news.php'; ?>
etc.
對於子目錄頁面,我一直這樣做:
<?php include '../includes/logo.php'; ?>
<?php include '../includes/main_nav.php'; ?>
<?php include '../includes/news.php'; ?>
還有這個:
<?php include '../../includes/logo.php'; ?>
<?php include '../../includes/main_nav.php'; ?>
<?php include '../../includes/news.php'; ?>
到目前為止這么好,但我懷疑它不會繼續這么容易。
現在我需要包含這個文件:
top_five_news_stories.php
在這:
news.php
此時,我的相對路徑策略失敗,因為include中的include只能有一個路徑結構。
我已經閱讀了幾篇推薦使用絕對路徑的帖子:
dirname(__FILE__)
realpath(dirname(__FILE__)
$_SERVER["DOCUMENT_ROOT"]
但是,它們都帶有與PHP配置,服務器配置或操作系統相關的某種警告。 換句話說,通常有人評論說它在他們的情況下不起作用,或者在IIS中不起作用,或者在UNIX中不起作用,或者其他東西。
我沒有看到的解決方案是我認為最簡單的解決方案:只需設置一個變量:
$base = "https://www.mywebsite.com/includes";
然后:
<?php include $base . "logo.php" ?>
考慮到我已經使用了以類似方式工作的HTML base
元素 ,這種方法讓我覺得簡單而有效。
但是因為在我讀過的任何帖子中沒有提到它,我想知道我是否忽視了一個潛在的問題。
坦率地說,如果我今天必須去制作,我會用這個:
<?php include $_SERVER['DOCUMENT_ROOT'] . '/logo.php" ?>
這對我有用,通常被提及。
但我想知道使用變量是否是一種可靠,有效的方法?
別
我建議不要使用任何需要PHP以外的東西,比如$ _SERVER變量。
$_SERVER['DOCUMENT_ROOT']
通常由Web服務器設置,這使得從命令行運行的腳本無法使用它。 所以不要使用它。
也不要使用url。 在一個URL路徑的部分是不一樣的磁盤上的文件的路徑。 實際上,該路徑甚至不能存在於磁盤上(想想Apache重寫)。
包括url還需要你打開allow_url_include
,如果使用不當會引入(嚴重)安全風險。
做
如果您支持的最小PHP版本是5.3(我希望它是!),您可以使用魔術常量 __DIR__
。 2個例子:
define(ROOT_DIR, __DIR__);
define(ROOT_DIR, realpath(__DIR__ . '/..'));
如果需要支持較低版本,請使用dirname(__FILE__)
。 2個例子:
define(ROOT_DIR, dirname(__FILE__));
define(ROOT_DIR, realpath(dirname(__FILE__) . '/..'));
確保ROOT_DIR
指向項目的根目錄,而不是指向其中的某個子目錄。
然后,您可以安全地使用ROOT_DIR
來包含其他文件:
include ROOT_DIR . '/some/other/file.php';
請注意,我定義的是常量( ROOT_DIR
),而不是變量。 變量可以更改,但是項目的根目錄不會更改,因此常量更適合。
真實路徑()
realpath()將任何相對的部分和符號鏈接解析為規范化的絕對路徑名。
所以給出以下文件和符號鏈接:
/path/to/some/file.php
/path/to/another/file.php
/path/to/symlink => /path/to/another
和/path/to/file.php
包含:
define(ROOT_DIR, realpath(__DIR__ . '/../symlink'));
然后ROOT_DIR
將成為/path/to/another
,因為:
__DIR__
等於/path/to/some
(所以我們得到/path/to/some/../symlink
) ..
是1目錄(所以我們得到/path/to/symlink
) symlink
指向/path/to/another
你真的不需要使用realpath()
,但是如果依賴於相對部分或符號鏈接,它確實會整理路徑。 它也更容易調試。
自動加載
如果您需要包含包含類的文件,最好使用自動加載 。 這樣你根本不需要include
語句。
使用框架
最后一點建議:這個問題已經解決了很多次。 我建議你去研究像Symfony,Zend Framework,Laravel等框架。如果你不想要一個“全棧”解決方案,那么看看像Silex,Slim,Lumen等微框架。
Jasper提出了一些好處,不使用DOCUMENT_ROOT的另一個原因是通過URL訪問的內容不必在此目錄中(例如,考慮Apache的別名,scriptalias和mod_user_dir)。
正如Barmar所指出的,PHP明確提供了聲明包含基本目錄的功能。 雖然這通常在配置中設置,但它可以在代碼中在運行時被覆蓋/添加 。 您永遠不希望在include / require指令中看到變量。 它打破了自動工具並隱藏了漏洞。 你也不應該包括使用文件包裝器。
在OO編程中有一個論點, 從不明確地使用include / require,而只是自動加載類定義。 但是,定位代碼的問題仍然存在。
簡短的回答是,對於您描述的問題,沒有最佳解決方案。 每種方法都有其缺點 - 最佳解決方案完全取決於上下文。 對於企業應用程序,設置include_path可簡化開發過程,如果無法從Web服務器直接訪問,則可增強安全性。 它還允許通過操縱路徑中多個條目的順序來選擇性地覆蓋功能。
另一方面,對於那些可能會對可能無法訪問文檔根目錄之外的目錄或更改默認配置的多個路徑感到困惑的技術用戶而言,這不是一個很好的模型。
使用相對路徑是一種強大而便攜的解決方案。 我不明白你的問題包括top_five_news_stories.php
。
下面顯示了一個為您提供企業和低端托管優勢的解決方案。 但是,它的缺點是需要將代碼添加到站點中的每個入口點(並且需要將應用程序安裝在指定的子目錄中):
define('APP_NAME', 'mikesdemo');
$base=substr(__DIR__, 0, strrpos(__DIR__, APP_NAME))
. APP_NAME . '/include';
set_include_path(get_include_path() . PATH_SEPARATOR . $base);
那么更復雜的用戶就可以......
mv /var/www/html/mikesdemo/include/* /usr/local/php/include/
為每個文件tipe定義一個路徑:
+root
|
+------app(D)(all php script MVC)
|
+------conf(D)(all php Config file)
|
+------assets(D)(all file js and css static image)
|
+------fileup(D)(all file Uploades)
|
+------index.php(F)(Procesor of petition http)
在您的索引中,您需要包含所有配置文件,如樣式C ++:
require_once ('conf/config.security.php'); #Configuration around Security in PHP
require_once ('conf/config.conpro.php'); #Configuration around Constantent
require_once ('conf/config.classlib.php'); #Lib class around Generic DB Conection ETC
require_once ('conf/config.classlibmvc.php'); #Lib class around MVC specific class
以及配置文件的示例:
$APP_DIR_CLASS = $_SERVER['DOCUMENT_ROOT'] . '/app/classgeneric/';
if (!defined('DBMANAGER_CLASS')) define('DBMANAGER_CLASS' ,'class.managerdb.php' );
require_once $APP_DIR_CLASS . DBMANAGER_CLASS;
當你在一個班級並且需要使用DB類時,你可以輕松地調用它:
class Class_Exmaple{
public function __construct(){
$this -> DBMANAGER = new Class_BDManager();
}
public function __destruct(){
$this -> DBMANAGER = new Class_BDManager();
}
public function ConsultDB(){
$query ='Selec * From Tablename';
$result = $this -> DBMANAGER -> ExecuteQ($query);
print_r(result);
}
}
是一種簡單的實施方法,但您需要了解有關注射和類裝載機的更多信息。
在項目中要求/包含內部腳本沒有 “ 正確的方法 ”。 很多(大多數)MVC框架在路由器對象中使用類似的最佳實踐來進行全局文件訪問。
我們舉一個例子,這是我們的目錄基礎結構:
App/
Controllers/
Controller.php
Models/
Model.php
Views/
View.php
404/
index.php
index.php
.htaccess
在我們的.htaccess
我們將對服務器根目錄中的index.php
進行rewrite
規則。
在這個文件中,我們實際運行整個軟件。 例如,這是一個很棒的路由器我使用AltoRouter 。
首先,我們需要添加一種方法來阻止直接瀏覽器訪問以及任何控制器,模型和視圖的錯誤路徑:
define( 'ERROR_PATH', strtolower(explode( '/', $_SERVER['SERVER_PROTOCOL'][0]) . '://' . $_SERVER['SERVER_NAME'] . '/404' );
define( 'IN_APP', 0 );
然后在您的控制器,模型和視圖中使用,例如:
if( !defined( 'IN_APP' ) ) {
header('Location: ' . ERROR_PATH);
exit();
}
如果在此實例中聲明__FILE__
( index.php
),則文件路徑將是根文件路徑,因此我們可以以任何方式使用它(最佳實踐是全局定義)。
define( '_DIR_', dirname( __FILE__ ) );
然后開始要求你的文件:
$includeFiles = [
glob( _DIR_ . '/Controllers/*.php' ),
glob( _DIR_ . '/Models/*.php' )
];
foreach( $includeFiles as $dir ):
foreach( $dir as $file ):
require_once( $file );
endforeach;
endforeach;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.