【问题标题】:Dynamically referencing to header and footer in all PHP pages within different directories and sub-directories动态引用不同目录和子目录中所有 PHP 页面的页眉和页脚
【发布时间】:2014-10-01 23:40:02
【问题描述】:

更新 1: 要清楚了解正在发生的事情,您可以download a snippet of the script from here.

我正在一个新网站上工作,该网站在所有 PHP 页面中都有相同的 headerfooter

在标题中,我引用了网站中的其他常见文件,例如 .css.jsfunctionsclassesdb connection 等。

例如,default.css/common/stylesheets/

而我的 header.php 和 footer.php 在/common/html/ 文件夹中

所以我的 header.php 文件是这样的

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>The Header</title>
  <link rel="stylesheet" href="common/stylesheets/default.css">
</head>
<body>

在我的网站index.php 中,我包含了标题&lt;?php include('common/html/header.php'); ?&gt;,这工作正常......但是当我在其他目录或子目录中的其他php页面中包含标题时出现问题,例如/pages/admin/dashboard.php,一切都搞砸了,该页面不再链接到 default.css 文件。

所以,我正在寻找的是一种方法或逻辑,我可以在其中引用每个 PHP 页面中的这些公共文件和文件夹,无论其位置如何;例如站点根目录、站点根目录中的目录或子目录……等等……

这是我网站根目录的图片

非常感谢您的帮助...

附注我尝试在config.inc.php 文件中使用一些超全局变量(例如$_SERVER[''])来定义路径,然后将该文件包含在header.php 中。但我不知道哪个会动态地继续引用那些公共文件夹和文件,无论 PHP 页面在哪里。


更新 1: 要清楚了解正在发生的事情,您可以download a snippet of the script from here.

【问题讨论】:

  • 如果我没记错的话,common/stylesheets/default.css 在当前位置寻找一个名为 common 的文件夹,它应该是 /common/stylesheets/default.css,它会进入根目录并获取 common 文件夹
  • @Class 当使用/common/stylesheets/defaults.css 时页面没有链接到default.css 文件,当我查看页面源时,链接是localhost/common/stylesheets/defaults.css,所以你可以看到sitename不见了。另一方面,当使用common/stylesheets/default.css 时,它可以工作并且页面源将链接显示为localhost/sitename/common/stylesheets/default.css
  • @Class 它包含 php 内容,但我删除了它们,因为它们与问题无关并保持代码干净整洁
  • defaults !== default 您可能需要在每个网址/链接中添加sitename,例如/sitename/common…
  • @Class, defaults 是一个错字,抱歉。仅供参考,我在帖子中添加了一个下载链接到脚本的 sn-p。

标签: php html content-management-system


【解决方案1】:

使用完全限定或绝对 URL 来引用您的资产通常是个好主意:

<link rel="stylesheet" href="http://www.sitenamecom/some/path/to/common/stylesheets/default.css">

由于在很多地方您需要正确的 URL 库来访问不同的文件,您可以定义一个具有 Web 根的常量:

define('WEB_ROOT', 'http://www.sitename.com');

然后您可以定义其他常量来访问系统的不同部分:

define('WEB_ASSETS', WEB_ROOT . '/common');

因此,header.php 中的样式表链接将是:

<link rel="stylesheet" href="<?php echo WEB_ASSETS; ?>/stylesheets/default.css">

对于include 文件,原理相同,只是在这种情况下您不使用 URL,而是使用文件系统的路径。没有真正的动态方法来解决这个问题,这一切都归结为绝对路径。

这里的问题是,您本地开发环境中的树结构可能(而且肯定不会)与您的服务器相匹配。因此,在位于应用程序根目录的配置文件中,您可以定义:

define('APP_ROOT', dirname(__FILE__));

然后让我们以admin/index.php 文件为例:

include '../../../config.inc.php'; 
include APP_ROOT . '/sitename/common/html/header.php';

这里的棘手部分包括配置。因为,在您这样做之前,APP_ROOT 将不可用,因此需要相对路径才能到达它,并且无法逃脱该路径;除非您可以完全信任首选的绝对形式:

include '/some/path/to/config.inc.php'; 

正如我之前所说,如果应用程序在不同的环境中进行测试,那么前面的斜线将是一个问题,因为some/path/to 总是相同的情况很少见。

【讨论】:

    【解决方案2】:

    这是不使用 index.php 进行集中化的结构的常见问题。也许您可以尝试添加另一个包含,将您的目录定义为伪常量并将它们添加到您的资产 url。

    或者您可以解析请求 url 的深度,并自动将所需的 ../ 级别添加到您的资产 url。我已经为我过去的一个项目做到了这一点。

    不过,我必须警告您,解决问题的根源(缺乏集中化)比添加变通办法更好。它肯定会比你想象的更快地回来困扰你。

    【讨论】:

    • @SULTAN:抱歉,我无法再访问该代码了。我将尝试重新创建我之前所做的嵌套算法并将其发布在这里。谢谢。
    【解决方案3】:

    $_SERVER['DOCUMENT_ROOT'] 可能就是您要查找的内容。

    <?php
    require_once($_SERVER['DOCUMENT_ROOT'] . "/sitename/common/html/header.php");
    

    这应该适用于任何目录。如果您希望它比输入“站点名称”更动态一点,您可以这样做:

    <?php
    $sitename = explode("/", $_SERVER['REQUEST_URI']);
    require_once($_SERVER['DOCUMENT_ROOT'] . "/" . $sitename[1] . "/common/html/header.php");
    

    【讨论】:

      【解决方案4】:

      您需要将您的&lt;link rel="stylesheet" href="common/stylesheets/default.css"&gt; 更改为&lt;link rel="stylesheet" href="../../common/stylesheets/default.css"&gt;

      【讨论】:

      • 在哪个页面改?
      • 使用相对链接对于多个级别的子目录来说很笨拙。 HTML 标签的 'href' 属性中的前斜杠将浏览器定向到文档根目录,如 webserver 实例给出的那样。
      【解决方案5】:


      这是 php.ini 中的一个简单修改,为每个脚本包含 footer.php 和 header.php

      auto_append_file=ABSOLUTE_PATH/footer.php
      auto_prepend_file=ABSOLUTE_PATH/header.php
      

      如果您在easyPhp、xampp、....下运行,请重新启动您的Apache。
      警告:此配置将应用于所有使用修改后的 PHP 执行的项目

      【讨论】:

      • 我很确定 :),你能试试告诉我吗?
      • 是的,我刚刚在我的 xampp 中对其进行了测试,我猜它正在影响 htdocs 中的所有其他网站
      【解决方案6】:

      试试&lt;link rel="stylesheet" href="/common/stylesheets/default.css"&gt;

      注意前导斜杠...这会将服务器定向到文档根目录。

      我试过了,效果很好。

      我的树:

      /var/www/html/
          subdir/
              body.php
          layout/
              header.php
              footer.php
          css/
              style.css
      

      header.php

      <html>
        <head>
          <link rel="stylesheet" href="/css/style.css">
        </head>
        <body>
          <p>Header.</p>
          <hr>
      

      body.php

      <?php
      include($_SERVER['DOCUMENT_ROOT'].'/layout/header.php');
      echo "Body.<br>";
      include($_SERVER['DOCUMENT_ROOT'].'/layout/footer.php');
      ?>
      

      footer.php

        </body>
      </html>
      

      style.css

      body {
        color: red;
      }
      

      在浏览器中查看http://localhost/subdir/body.php,我得到了预期的结果:“Header”和“Body”是红色的。

      【讨论】:

      • 我已经在我的网站上尝试了您的步骤,但不幸的是它没有奏效!使用 include($_SERVER['DOCUMENT_ROOT'].'/layout/header.php'); 时收到警告:Warning: include(C:/xampp/htdocs/common/html/header.php): failed to open stream: No such file or directory in C:\xampp\htdocs\sitename\index.php on line 1 Warning: include(): Failed opening 'C:/xampp/htdocs/common/html/header.php' for inclusion (include_path='.;\xampp\php\PEAR') in C:\xampp\htdocs\sitename\index.php on line 1
      • 嗯...检查权限?应该是 755。
      • 还要确保将“/layout/header.php”更改为头文件相对于文档根目录的实际位置。这只是我使用所描述的目录结构的示例。
      • 好的,但是什么许可?网站名称? ...另外,我已将 /layout/header.php 更新到我的文档根目录,但出现了该错误,如果您查看错误,您将看到 C:/xampp/htdocs/common/html/header.php,因此它指向正确的 header.php 文件除了路径中缺少sitename
      【解决方案7】:

      我会将您网站的文档根目录存储在一些定义中:

      define('DOCROOT', $_SERVER['DOCUMENT_ROOT']);
      

      在您随处包含的 PHP 文件中执行此操作,最好是在某个引导 PHP 文件中。

      然后你需要在你的包含行中添加你的路径:

      <?php include(DOCROOT . "/common/html/header.php"); ?>
      

      你也看过include_once吗?

      【讨论】:

        【解决方案8】:

        你试过 PHP 的 set_include_path 吗?

        您可以在一个 set_include_path 中添加多个路径,并用“:”分隔它们。 set_include_path('/home/mysite/includes1:/home/mysite/includes2')。 PHP.net -> set_include_path

        【讨论】:

          【解决方案9】:

          即使不迁移到完整的前端控制器(和 MVC)设置(这会很好),如果您引入一个简单的类似引导程序的文件,您也会省去很多麻烦。

          它不会与您当前的设置完美结合,因为您的文件在不同的位置和子文件夹中包含系统的不同部分(即 header.php)。

          让 header 加载第一个输出的东西 - 即 doctype、head 和 head 链接等 - 在您的基本结构中很好,但是您现在遇到了一些限制,如果不让您的 header.php 混乱,或者包括许多header.php 之前的其他文件。

          在更可靠的框架设计中,html 和 doctype 输出是在启动和加载了许多其他内容之后,以允许控制所述 html 和 doctype。

          但为了帮助您解决问题,只需在加载/包含其他任何内容之前加载引导程序。

          引导

          引导程序将在整个应用程序中加载共享资源、常用数据和路径(等)。
          然后,如果您找到一个场景,您可以在将来在引导程序中添加任何其他内容。

          您的引导程序中的一个简单示例:
          bootstrap.php(必须驻留在您的根网络文件夹中才能使以下常量起作用)

          // Define root folder
          define ('FOLDER_ROOT', __DIR__);
          

          然后,您可以在整个应用程序中引用该常量 (FOLDER_ROOT) 来确定根文件夹,并根据需要处理子文件夹。

          所以,使用您当前的设置:
          index.php(我假设在根文件夹中)

          include('bootstrap.php');
          include(FOLDER_ROOT.'/common/html/header.php');
          // Everything else
          

          因此,您可以在引导程序中设置其他内容,例如定义默认文档类型或字符编码、设置错误管理。
          尽管您通常会在引导后设置诸如 doctype 之类的内容,但可以在类、路由器、某些控制器甚至模板中进行设置。
          但是当您使用通用文件包含而不是使用更传统的框架设计模式时,这种方式至少现在可以为您省去一些麻烦,并且可能更进一步。

          所以又在bootstrap.php:

          // Define root folder
          define ('FOLDER_ROOT', __DIR__);
          // Define CSS folder using root folder constant above
          define ('FOLDER_CSS', FOLDER_ROOT.'/common/stylesheets/');
          

          然后在header.php:

          echo '<link rel="stylesheet" type="text/css" href="'.FOLDER_CSS.'default.css">';
          

          子文件夹(即 /admin)

          现在在子文件夹中,例如 /pages/admin/dashboard.php 等,您无法访问这些常量,因为您正在“跨应用程序”单独加载头文件和其他模板之类的东西。
          所以设置你的根文件夹变成了一场战斗,而且你现在要管理它两次!

          您可以尝试在管理文件夹中加载根引导文件。
          所以在dashboard.php 中,类似:

          include('/bootstrap.php');
          // OR (more likely)
          include('../../bootstrap.php');
          

          但这变得很混乱,在不同的地方调用 bootstrap,也不得不以不同的方式调用它。

          这并不理想,但它是可行的,因为如果您在管理区域中加载了引导程序,那么您在管理区域中设置了根路径,因此从管理文件管理其他文件应该更容易。

          您可以尝试使用新的管理员专用引导文件,例如在/pages/admin/ 中,有adminBootstrap.php
          但是随后您为 root 设置了两个不同的常量,并且可能更多的常量来访问您的 common 和 css 文件和文件夹。在 Web 根路径中的文件中设置 Web 根路径很容易,但从另一个文件夹设置 Web 根路径可能很棘手(有时)。

          样式表

          您提到使用/common/stylesheets/defaults.css(带有前面的斜杠)不起作用并导致源代码显示localhost/common/stylesheets/defaults.css
          这可能表明您需要配置 DocumentRoot。

          在 Linux 上,它位于 /etc/apache2/sites-available/,然后是 default 文件,或者如果您配置了自己的虚拟站点,则进入每个站点。

          您的 DocumentRoot 设置是什么?

          虽然如果您让引导程序在管理区域内工作,这个问题可能会消失,使用常量FOLDER_CSS

          文件夹结构

          我还认为你应该整理你的文件夹,因为你似乎把东西分成了不合逻辑的文件夹名称(也许对你来说是合乎逻辑的,但是当你了解更多并在一年内回来时,或者另一个开发者尝试使用它?)。

          例如我不知道文件夹html 到底要包含什么,因为HTML 是一种协议,最终您的应用程序将提供HTML。

          稍微了解一下 MVC。不要深入,因为它需要大量的阅读/学习,但如果你掌握了基础知识,你就可以整理自己的结构,以比现在更合乎逻辑地创建自己的演示与业务的逻辑分离。

          前置控制器

          如果你没有使用包含文件,而是有一个框架,它加载引导程序和应用程序范围的配置、错误管理和其他东西,那么当你加载 HTML(你的页眉、页脚等)时,它们将拥有所有这些无论您尝试从哪个子文件夹加载网页,应用程序(根文件夹常量等)都会预加载。

          但是,当您这样做时,您需要将这些内容手动包含在不同的文件中,在子文件夹中。

          虽然您通过在包含文件中包含 doctype、head 等并重新使用它们来引入少量的 DRY(不要重复自己),但您仍然需要在重新使用这些包含文件时重复自己- 在需要的地方使用它们。

          另外,如果您想重新设置与主站点不同的管理样式怎么办?您必须包含不同的头文件或不同的样式表,或者只是将所有代码放在同一个样式表中。

          我在胡扯,但希望我说的很清楚,您会明白为什么使用标题包含只是朝着正确方向和小型网站迈出的一小步。我敢肯定,通过在每个文件中输入 head/doctype 等,您自然而然地使用了这些包含文件。

          但是,现在您正试图突破其他方向,就像您的管理区域一样,您可以看到限制,并且随着整个应用程序的增长,包含这些相同的文件变得越来越难以管理。

          因此,如果您有一个前端控制器类型设置,在您的 dashboard.php 中,您将能够简单地使用在根引导文件中设置的常量,以及在核心应用程序加载后可以访问的任何其他子文件夹.

          EG(如果使用类似模式的前端控制器) dashboard.php

          include(FOLDER_ROOT.'/common/html/header.php');
          

          我知道我已经对前端控制器进行了抨击,但几年前我正处于你现在所处的阶段,我的所有文件都包括 header.php,然后是页面内容,然后是页脚.php 等,而我开始使用前端控制器。
          真的好多了!

          这是一个公平的学习曲线(在各种方向和方法、要求等方面都有学习曲线),因此如果您想进一步研究,这将由您决定。

          我现在有了自己的基本 MVC 前端控制器系统,我只是简单地将一个新网站页面的新文件放入 view/pages 文件夹中,该页面可以立即在浏览器中使用(系统会执行其他所有操作)。

          【讨论】:

            猜你喜欢
            • 2012-08-03
            • 2016-04-30
            • 2015-02-10
            • 1970-01-01
            • 2018-10-10
            • 2013-06-22
            • 2014-09-29
            • 2016-04-15
            • 2011-08-17
            相关资源
            最近更新 更多