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

问题描述 投票:0回答:6

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

//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 类,但它似乎不起作用?

php pdo namespaces autoload
6个回答
6
投票

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

use
语句。

因此,如果您没有

use
语句,则必须使用前导反斜杠引用 PDO 和其他全局类 - 即
$obj = new \PDO();

如果您有一个引用该类的

use
语句,那么您可以仅通过类名来引用它:

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

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

use


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();
    }
}

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

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

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


0
投票

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

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


0
投票

附录:使用全局命名空间中的类作为函数类型提示,似乎需要“使用

© www.soinside.com 2019 - 2024. All rights reserved.