使用PHP变量实例化一个类 - 命名空间的问题

时间:2013-10-28 18:05:19

标签: php namespaces

以下所有示例都基于所有文件都在正确位置的保证。我高音检查了这个。

(1)这在不使用名称空间时有效:

$a = "ClassName";
$b = new $a();

这不起作用:

// 'class not found' error, even though file is there

namespace path\to\here;
$a = "ClassName";
$b = new $a();

这项工作:

namespace path\to\here;
$a = "path\to\here\ClassName";
$b = new $a();

因此,当使用变量实例化类时,似乎忽略了名称空间声明。

有没有更好的方法(比我上一个例子)所以我不需要经历一些代码并更改每个变量以包含命名空间?

2 个答案:

答案 0 :(得分:5)

命名空间始终是完整类名的一部分。使用一些use语句,您只能在运行时为类创建别名。

<?php

use Name\Space\Class;

// actually reads like

use Name\Space\Class as Class;

?>

类之前的名称空间声明只告诉PHP解析器该类属于该名称空间,对于实例化,您仍然需要引用完整的类名(包括如前所述的名称空间)。

要回答您的具体问题,不,没有比问题中包含的最后一个例子更好的方法。虽然我用双引号字符串来逃避那些不好的反斜杠。*

<?php

$foo = "Name\\Space\\Class";
new $foo();

// Of course we can mimic PHP's alias behaviour.

$namespace = "Name\\Space\\";

$foo = "{$namespace}Foo";
$bar = "{$namespace}Bar";

new $foo();
new $bar();

?>

*)如果使用单引号字符串,则无需转义。

答案 1 :(得分:1)

在字符串中存储类名时,需要存储完整的类名,而不仅仅是相对于当前名称空间的名称:

<?php
// global namespace
namespace {
    class Outside {}
}

// Foo namespace
namespace Foo {
    class Foo {}

    $class = "Outside";
    new $class; // works, is the same as doing:
    new \Outside; // works too, calling Outside from global namespace.

    $class = "Foo";
    new $class; // won't work; it's the same as doing:
    new \Foo; // trying to call the Foo class in the global namespace, which doesn't exist

    $class  = "Foo\Foo"; // full class name
    $class  = __NAMESPACE__ . "\Foo"; // as pointed in the comments. same as above.
    new $class; // this will work.
    new Foo; // this will work too.
}