[英]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.