PHP包含所需的文件策略

PHP包含所需的文件策略,php,Php,我正在设置一个php项目,但不太熟悉如何正确使用php的include/require命令。我的布局当前如下所示: /public --apache points into this directory /public/index.php /public/blah/page.php /utils/util1.php -- useful classes/code are stored in other directories out here /dbaccess/d

我正在设置一个php项目,但不太熟悉如何正确使用php的include/require命令。我的布局当前如下所示:

/public   --apache points into this directory  
/public/index.php  
/public/blah/page.php  
/utils/util1.php       -- useful classes/code are stored in other directories out here  
/dbaccess/db1.php  

dbaccess/db1.php  



require '../utils/util1.php
require_once dirname(__FILE__) . '/../utils/util1.php');
public/index.php

require '../dbaccess/db1.php'
public/blah/page.php

require '../../dbaccess/db1.php'
php“include”文档中的问题是:

如果文件名以./或../开头,则仅在当前工作目录中查找

因此public/blah/page.php失败,因为它包含dbaccess/db1.php,当它试图包含util1.php时,dbaccess/db1.php会崩溃。它失败是因为它的相对路径来自public/blah/中的原始脚本,而不是dbaccess/

这看起来很愚蠢——db1.php必须知道它是从哪里包含的,从哪里不起作用

我见过这样的策略:

/public   --apache points into this directory  
/public/index.php  
/public/blah/page.php  
/utils/util1.php       -- useful classes/code are stored in other directories out here  
/dbaccess/db1.php  

dbaccess/db1.php  



require '../utils/util1.php
require_once dirname(__FILE__) . '/../utils/util1.php');
这显然是可行的,因为现在这条路是一条绝对的路,但对我来说真的很奇怪


这正常吗?我应该继续沿着这条路走下去,还是我在这里遗漏了一些明显的东西?

为什么不根据它的完整路径要求它呢

例如,/sharedhost/yourdomain.com/apache/www是您的文档根,那么为什么不使用

require('/sharedhost/yourdomain.com/apache/www/dbutils.php');
这还有一个好处,即您可以将您的包含内容存储在wwwroot的外部,这样它们就不太可能通过web意外暴露

您还可以设置一个全局变量,该变量等于/sharedhost/yourdomain.com/apache/它的一部分,以便可以移动站点

require(WWWROOT . '/dbutils.php');

使用配置脚本设置项目的“安装根目录”,然后使用绝对路径。具有多个包含的相对路径在php中是一个令人头痛的问题

定义(“INSTALL_ROOT”,“/path/to/www/project”)

需要一次(安装ROOT./util1.php)

我使用

require '../path/to/file.ext';
没有问题

还要求语句不是函数,因此应将其用作

require '/path/to/file.ext';
不是


请记住,它从当前工作目录开始,然后查看包含路径。如果要引用某个中心根目录(或多个)中的所有路径,可以将该目录添加到php.ini文件中,也可以使用
set_include_path($path.path_separator.get_include_path())以编程方式进行

我建议采用一种抽象策略

  • 在应用程序页面区域中,有一个包含所有页面的文件

  • 这个“本地”包含文件有一个任务:查找应用程序页面区域之外的包含文件。然后它包括了这一点。它可能像

  • 第二个文件是库结构的单一入口点。它,或者它包含的其他东西,有一项工作就是找到所有东西的位置,包括它

  • 这种结构意味着您只有一个文件作为库的入口点,它如何找到库的其余部分不是应用程序页面的问题。这也意味着在应用程序区域中只有一个文件知道如何找到库的入口点

    如果您需要不同的应用程序页面加载不同内容的方法,我建议使用模块化方法。这可以是在主include之前设置的全局数组,也可以是通过名称调用请求库的函数。是的,这是主库文件声明所有内容所在位置的常量的一种稍微花哨的方式——但它消除了执行
    include library_DIR.'/utils/util.php'的诱惑
    直接导致以后将
    util.php
    utils
    移动到
    misc/util
    不必要的困难


    链式文件的另一个优点是,这样可以更容易地重新定位代码库,从而使多个版本都可以运行。它使应用程序有一棵树,库有另一棵树成为可能。这意味着另一个应用程序可以使用您的库。事实上,如果您想进一步帮助隔离,可以进一步扩展链接

    define('MYAPP_BASEDIR',realpath('.')

    然后我引用了所有与之相关的东西

    。。。如果您的include目录专门与类文件相关,并且您能够对它们进行命名,以便可以从该类派生include文件名,那么您可能需要查看


    后一部分并不是对您的问题的直接回答,但如果您正在为使用的每个类执行include操作,它会非常方便。

    通常,标准约定是这样的:如@grepsedawk所说,您需要定义一个常量,其中包含项目文件夹的根,如果您可以定义include文件夹的根:

    define('APP_ROOT', dirname(__FILE__));
    define('INCLUDE_ROOT', APP_ROOT . "/includes");
    
    注意:常量名称必须是字符串

    另外,您会注意到我使用的是
    dirname(\uuu文件\uu)。如果将常量定义文件放在子目录中,则可以执行
    dirname(dirname(_file__))
    ,它相当于
    。/

    现在还有一些其他的警告。虽然路径分隔符是一个很酷的常数,但不需要它。Windows接受路径名中的/或\作为路径分隔符,并且由于只使用Linux的用户/作为路径分隔符,因此请始终使用/而不是重复引用
    路径\分隔符来破坏代码

    现在已经定义了根常量,当需要包含配置文件时,您将执行以下简单操作:

    include INCLUDE_ROOT . '/path/to/some/file.php';
    
    您可能希望在根目录的引导脚本中使用常量定义(上面的
    定义(…)
    ):

    引导将包含常量文件的定义(或
    include
    ),以及每页所需的任何文件的
    include

    最后,您可能不使用最后一个标准约定,但如果您开始进行面向对象编程,最常用的方法(PEAR标准)是使用u分隔名称空间来命名类:

    class GlobalNamespace_Namespace_Class
    //...
    
    include_dir/
      GlobalNamespace/
          Namespace/
              Class.php
    
    require_once APP_ROOT."/path/to/your/script.php";
    
      <Environments>
        <Application name="www.domain.com" namespace="">
          <Constants>
            <Constant name="APP_ROOT" value="/full/path/to/project/source" />
          </Constants>
          <Constants>
            <Constant name="WEB_ROOT" value="/full/path/to/project/public" />
          </Constants>
        </Application>
      </Environments>
    
      require_once "./relative/path/to/script.php";
    
    <map>
        <path classname="MyClass">${project_directory}/libs/my_classes/MyClass.php</path>
        <path classname="OtherClass">${project_directory}/libs/some_new/Other.php</path>
        <!-- its so flexible that even external libraries fit in -->
        <path classname="Propel">${project_directory}/vendors/propel/Propel.php</path>
        <!-- etc -->
    </map>
    
    <?php
    
    //You only need to paste the following line into your script once,
    //and it must come before you reference the public document root of your website.
    //Use $pubroot.'/path_from_public_document_root_to_file/filename.php
    
    $pubroot = (str_replace(($_SERVER['PHP_SELF']), '', (str_replace('\\', '/', (realpath(basename(getenv("SCRIPT_NAME"))))))));
    
    
    //uncomment the next line to show the calculated public document root
    //relative to the document root.
    
    //echo ("$pubroot");
    ?>