4

以下所有示例均基于所有文件都存在于正确位置的保证。我已经三倍检查了这一点。

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

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

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

4

2 回答 2

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

?>

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

于 2013-10-28T18:27:35.587 回答
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.
}
于 2013-10-28T18:46:03.827 回答