PHP在全局命名空间中使用类

时间:2013-01-11 16:06:43

标签: php pdo namespaces autoload

我有一个使用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类,但它似乎不起作用?

5 个答案:

答案 0 :(得分:5)

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

所以,如果你没有use语句,那么必须用前导反斜杠引用PDO和其他全局类 - 即$obj = new \PDO();

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

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

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

答案 1 :(得分:0)

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

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

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

然后假设我们在Library_1中有一些/var/www/Libs/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();
    }
}

答案 2 :(得分:0)

这很有效,你的问题就在于它。

的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;
    }
}

答案 3 :(得分:0)

要访问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;
        }
    }
}

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

答案 4 :(得分:0)

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

  

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