【问题标题】:PHP use class in global namespacePHP 在全局命名空间中使用类
【发布时间】:2012-12-26 06:17:44
【问题描述】:

我有一个使用 PDO 的 DB 包装类,并在构造函数中创建了一个 PDO 对象。包装类在我们的命名空间中,我们正在使用自动加载器。问题是在我们的命名空间中找不到 PDO 类,所以我尝试使用全局命名空间,如 here 所述。

//Class file
namespace Company\Common;
class DB {
    private function __construct(){
        $this->Handle=new PDO(...);
    }
}

有了这个,我得到了这个(如预期的那样):

Warning: require(...\vendors\Company\Common\PDO.class.php): failed to open stream

如果我这样做:

namespace Company\Common;
use PDO;

我明白了:

Fatal error: Class 'DB' not found in ...\includes\utils.php

并且 utils.php 在错误行中包含了这个,在实现命名空间之前它工作得很好:

DB::getInstance();

我也试过这个:

namespace Company\Common;
class DB {
    private function __construct(){
        $this->Handle=new \PDO(...);
    }
}

它试图像最初那样在我们的命名空间中加载 PDO 类。

我该如何解决这个问题?我以为通过 use PDOnew \PDO 会加载全局 PDO 类,但它似乎不起作用?

【问题讨论】:

  • 那个 PDO 类在什么命名空间中?
  • 你在哪里调用 DB 类? use \PDO; 是正确的,问题是 elsewere。
  • @shadyyx PDO 类是 PDO 库中的全局 PDO 类。
  • 您是否将 include_path 设置为也包含该 PDO 库?
  • @Glavic 我最初在一个非自动加载的文件中调用它,该文件用于实用程序功能。它只是做 DB::getInstance() 正常工作。

标签: php pdo namespaces autoload


【解决方案1】:

在命名空间 PHP 中,对类的引用必须包含该类的命名空间,除非您有包含该类或其部分命名空间的 use 语句。

因此,如果您没有 use 声明,则必须使用前导反斜杠引用 PDO 和其他全局类 -- 即 $obj = new \PDO();

如果您有一个引用该类的use 语句,那么您可以仅通过类名来引用它:

use PDO;
....
$obj = new PDO();

如果您要引用很多全局类,如果您想避免每次都使用反斜杠,则需要单独 use 每个类。

【讨论】:

    【解决方案2】:

    通常在我们的项目中,我们会这样设置包含路径:

    set_include_path('PATH_TO_GLOBAL_LIBS; PATH_TO_LIBRARY_1; PATH_TO_LIBRARY_X; PATH_TO_DOCUMENT_ROOT');
    

    这样我们告诉 PHP (Apache) 在这些路径中搜索任何应该被自动加载器包含的类。

    然后假设我们在/var/www/Libs/library_1 中有一些Library_1 并且这个路径被添加到include_path 我们可以这样做:

    namespace Company\Common;
    
    Class DB {
        private function __construct() {
            $this->Handle = new \Library_1();
        }
    }
    

    应该是一样的

    namespace Company\Common;
    
    use \Library_1;
    
    Class DB {
        private function __construct() {
            $this->Handle = new Library_1();
        }
    }
    

    【讨论】:

    • 在实现命名空间之前一切正常。我一直在使用自动加载器来加载所有这些。那么 include_path 还会成为问题吗?
    【解决方案3】:

    这行得通,你的问题是 elsewere。

    index.php

    <?php
    include('_db.php');
    use Company\Common\DB;
    new DB;
    

    _db.php

    <?php
    namespace Company\Common;
    use \PDO;
    
    class DB {
        public function __construct() {
            $this->Handle = new PDO;
        }
    }
    

    【讨论】:

    • 我唯一注意到的是,如果我在注册自动加载器后执行 DB::getInstance(),它工作正常,DB 类被包含在内并且可以使用。如果我尝试在 utils.php(不是类)中使用 DB::getInstance(),它说它找不到类 DB。
    • 就像我说的,问题出在其他地方。当您在 utils.php 中时,听起来好像没有加载自动加载器...
    • 似乎use Company\Common\DB; 仅适用于我使用它的文件。如果我在 utils.php 中也有它,它工作正常。 use 语句仅适用于当前文件并且不会级联整个包含的文件,这是真的吗?编辑,是的(“导入规则是基于每个文件的,这意味着包含的文件不会继承父文件的导入规则。”)
    • @JasonKaczmarsky,是的,这是真的。
    【解决方案4】:

    要访问像PDODateTime 这样的全局对象,您需要在它们前面加上反斜杠。所以你有两个选择。

    首先,use 您希望在命名空间类文件中使用的类:

    <?php
    namespace Vendor;
    
    use \PDO;
    use \PDOException;
    
    class MyClass
    {
        public function __construct()
        {
            try {
                $db = new PDO($dsn, $user, $pass);
                $db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
            }
            catch (PDOException $e) {
                echo $e->getMessage();
                exit;
            }
        }
    }
    

    或者只在你的类中使用反斜杠前缀声明:

    <?php
    namespace Vendor;
    
    class MyClass
    {
        public function __construct()
        {
            try {
                $db = new \PDO($dsn, $user, $pass);
                $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            }
            catch (\PDOException $e) {
                echo $e->getMessage();
                exit;
            }
        }
    }
    

    就个人而言,我更喜欢第一种方法。

    【讨论】:

      【解决方案5】:

      解决了。我没有意识到命名空间的别名仅适用于当前文件,而不适用于任何未来包含的文件。在 PHP.net 上找到这个也适用于别名:

      导入规则基于每个文件,这意味着包含的文件不会继承父文件的导入规则。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-04-07
        • 2013-11-22
        • 1970-01-01
        • 2012-11-07
        • 1970-01-01
        • 2012-08-22
        • 1970-01-01
        • 2010-10-31
        相关资源
        最近更新 更多