简体   繁体   English

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

[英]PHP use class in global namespace

I have a DB wrapper class that uses PDO and in the constructor I create a PDO object. 我有一个使用PDO的数据库包装器类,并在构造函数中创建了一个PDO对象。 The wrapper class is in our namespace and we are using an autoloader. wrapper类位于我们的名称空间中,并且正在使用自动加载器。 The issue is that the PDO class cannot be found within our namespace, so I tried using the global namespace as described here . 问题是在我们的名称空间中找不到PDO类,因此我尝试使用此处所述的全局名称空间。

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

With this, I get this (as expected): 有了这个,我得到了(如预期的那样):

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

If I do this: 如果我这样做:

namespace Company\Common;
use PDO;

I get this: 我得到这个:

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

And utils.php contains this on the error line, which worked fine before implementing namespaces: utils.php在错误行中包含此内容,在实现名称空间之前可以正常工作:

DB::getInstance();

Alternatively I tried this: 另外,我尝试了这个:

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

Which tried to load the PDO class within our namespace as it originally did. 它试图像最初那样在我们的命名空间中加载PDO类。

How can I resolve this? 我该如何解决? I thought by doing use PDO or new \\PDO it would load the global PDO class, but it doesn't seem to be working? 我认为通过use PDOnew \\PDO可以加载全局PDO类,但是它似乎没有用吗?

In Namespaced PHP, references to a class must include the namespace of that class, unless you have a use statement that includes that class or part of its namespace. 在具有命名空间的PHP中,对类的引用必须包含该类的命名空间,除非您具有包含该类或其部分命名空间的use语句。

So, if you have no use statement for it, then PDO and other global classes must be referenced with the leading backslash -- ie $obj = new \\PDO(); 因此,如果您没有use语句,则必须使用前导反斜杠来引用PDO和其他全局类,即$obj = new \\PDO();

If you have a use statement that references that class, then you may reference it by just the classname: 如果您有一个引用该类的use语句,则可以仅通过类名来引用它:

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

If you're referencing a lot of global classes, you'll need to use each of them individually if you want to avoid using the backslash every time. 如果要引用很多全局类,则要避免每次都使用反斜杠,则需要单独use它们。

Normally in our projects we do set include path like this: 通常,在我们的项目中,我们会设置包括以下内容的路径:

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

By this we tell PHP (Apache) to search these paths for any classes that should be included by autoloader. 这样,我们告诉PHP(Apache)在这些路径中搜索自动加载器应包含的任何类。

Then assuming we have some Library_1 in /var/www/Libs/library_1 and that this path is added to the include_path we could do this: 然后假设我们在/var/www/Libs/library_1有一些Library_1 ,并且将此路径添加到include_path中,我们可以这样做:

namespace Company\Common;

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

which should be the same as 应该与

namespace Company\Common;

use \Library_1;

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

This works, your problem is elsewere. 这有效,您的问题是其他的。

index.php index.php

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

_db.php _db.php

<?php
namespace Company\Common;
use \PDO;

class DB {
    public function __construct() {
        $this->Handle = new PDO;
    }
}

To access global objects like PDO and DateTime , you need to prefix them with a backslash. 要访问诸如PDODateTime类的全局对象,您需要在它们前面加上反斜杠。 So you then have two options. 因此,您有两个选择。

First, either use the classes you wish to use in your name-spaced class file: 首先, 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;
        }
    }
}

Or just use the backslash-prefixed declarations within your class: 或者只在类中使用反斜杠前缀的声明:

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

Personally, I prefer the first approach. 就个人而言,我更喜欢第一种方法。

Solved it. 解决了。 I didn't realize that aliasing a namespace only applies to the current file, and not any future included files. 我没有意识到别名空间仅适用于当前文件,不适用于将来包含的文件。 Found this on PHP.net which also applies to aliasing: 在PHP.net上发现了这一点,它也适用于别名:

Importing rules are per file basis, meaning included files will NOT inherit the parent file's importing rules. 导入规则是基于文件的,这意味着包含的文件将不会继承父文件的导入规则。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM