PHP包含相对src属性和Apache错误页面


PHP includes, relative src attributes, and Apache error pages

我正在使用一个404错误页面:

/error_pages/404.php

我有一个用于向用户显示各种消息的常规页面模板:

/message.php

我的错误页面是这样的:

require_once("../includes/core.php");
$message = "Sorry but we could no longer find the item that you were looking for";
$messageStart = "Not Found";
require_once("../message.php");

我有一个管理页面在:

/admin

现在我的问题是CSS文件和JS文件在message.php。如果404发生在文档根,则所有链接都解析到正确的位置,并且所有文件都包含在HTML中。如果404发生在/admin,所有链接都被解析,就像message.php/admin/message.php找到一样!

我已经尝试过使用像PATH_TO_ROOT这样的常量,它是每页定义的,或者它是由core.php根据$_SERVER["PHP_SELF"]的值定义的。

现在的问题在上面的方法是$_SERVER["PHP_SELF"]总是包含/error_pages/404.php,因此PATH_TO_ROOT将总是包含'../',并将搞乱所有404发生在文档根。

如果我在message.php本身中定义PATH_TO_ROOT,那么/admin中的所有404都会弄乱。

如何解决这个问题?

编辑:

我尝试使用$_SERVER["REQUEST_URI"]。CSS和JS文件现在被正确地包含了。问题是PHP包含。所有包含都是从404.php所在的/error_pages解析的。这些PHP包含确实使用PATH_TO_ROOT,所以基于REQUEST_URIPATH_TO_ROOT真的不那么好。

使用相对于站点的链接 root:

<link rel="stylesheet" href="/css/default.css" />

在路径的开头使用正斜杠来"开始"站点的根文件夹。这样,路径总是相同的。

在我自己的框架中这样做后,解决方案可能有点麻烦,而且web上许多其他人没有很好地记录。你必须考虑三个问题:

  • WEB根在哪里,你的引擎/框架代码在哪里
  • 你的引擎/框架的PHP文件根目录和相应的include/require在哪里
  • CSS/JS/Images/etc的正确路径计算

假设一些小细节,这些都可以很容易地解决。首先要做的假设是,您的框架将在一个已知的文件夹(称为框架),它将有一个已知的文件名(同样,框架.php)。然后在index.php处理程序中查找框架路径,可以使用:

// in index.php
$frameworkPath = './';
while((is_dir($frameworkPath))&&(!file_exists($frameworkPath.'framework/framework.php'))){
  $frameworkPath = ($frameworkPath!='./')?'../'.$frameworkPath:'../';
}
if(!file_exists($frameworkPath.'framework/framework.php')){
// some type of error handler here
}else require_once($frameworkPath.'framework/framework.php');
// in framework.php
if(!defined('FRAMEWORK_PATH')){
  $frameworkpath = str_replace("''", '/', dirname(__file__));
  if(substr($frameworkpath, -1)!='/') $frameworkpath .= '/';
  define('FRAMEWORK_PATH', $frameworkpath);
}
// now your requires become require_once(FRAMEWORK_PATH.'filename/relative/framework.php');

然后我们需要计算站点的安装路径。我们可以使用DOCUMENT_ROOT和"当前访问的文件"的路径来做到这一点。类似以下内容:

$serverPath = $_SERVER['DOCUMENT_ROOT'];
$thisPath = @realpath(dirname('./'));
$thisPathLength = strlen($thisPath);
$SitePath = '/'.str_replace('''','/', substr($thisPath, strlen($serverPath), $thisPathLength)).'/';

这也为我们提供了站点PHP文件的绝对路径,我们可以利用PHP包含系统允许我们提供绝对文件路径而不仅仅是相对路径来包含用户脚本的事实。这个路径是用于用户脚本包含和要求的。例如,如果你想在/path/to/site/user_script.php中包含一个文件,你可以输入a:

require_once($thisPath.'user_script.php');

SitePath现在可以用来设置包含相关的CSS/JS/等文件。所以不用写

<img src="img.jpg" />
你说

<img src="<?php echo $SitePath;?>img.jpg" />.

如果你感兴趣的话,我现在的框架是可以共享的,最终我将把它开源发布,但我还没有做文档,所以这是一个你自己冒险的事情:)。我将其扩展为使用SIMPLE_HTML_DOM_PARSER,以便它为设计人员更新源HTML中的标签,他们不必担心标签上的src, action, href等属性。当然,它减慢了渲染速度,但它使设计人员的工作更轻松:)

嗯,如果我理解你的问题,你真的想使用相对而不是绝对路径(如/css/style.css),我会尝试计算当前文档的深度,如:

$depth = substr_count($_SERVER["DOCUMENT_URI"], "/") - 1;

然后路径使用:

<link rel="stylesheet" type="text/css" href="<?=str_repeat("../", $depth)?>css/style.css" />

我没有测试代码,但它应该工作。试试吧。希望有所帮助