我有一个使用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 PDO
或new \PDO
它会加载全局PDO类,但它似乎不起作用?
答案 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)
要访问PDO
和DateTime
等全局对象,您需要在其前面加上反斜杠。所以你有两个选择。
首先,要在名称间隔的类文件中使用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上找到了这个,它也适用于别名:
导入规则是基于每个文件的,这意味着包含的文件不会继承父文件的导入规则。