代码说得比文字更好:
namespaces.php :
<?php
namespace foo;
use foo\models;
class factory
{
public static function create($name)
{
/*
* Note 1: FQN works!
* return call_user_func("\\foo\\models\\$name::getInstance");
*
* Note 2: direct instantiation of relative namespaces works!
* return models\test::getInstance();
*/
// Dynamic instantiation of relative namespaces fails: class 'models\test' not found
return call_user_func("models\\$name::getInstance");
}
}
namespace foo\models;
class test
{
public static $instance;
public static function getInstance()
{
if (!self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
public function __construct()
{
var_dump($this);
}
}
namespace_test.php :
<?php
require_once 'namespaces.php';
foo\factory::create('test');
如评论所述,如果我在call_user_func()
中使用完全限定名称,它会按预期工作,但如果我使用相对名称空间,则表示找不到类 - 但直接实例化可行。我是否因设计错过了某些内容或奇怪的?
答案 0 :(得分:7)
您必须在回调中使用完全限定的类名。
请参阅Example #3 call_user_func()
using namespace name
<?php
namespace Foobar;
class Foo {
static public function test() {
print "Hello world!\n";
}
}
call_user_func(__NAMESPACE__ .'\Foo::test'); // As of PHP 5.3.0
call_user_func(array(__NAMESPACE__ .'\Foo', 'test')); // As of PHP 5.3.0
我相信这是因为call_user_func
是来自全局范围的函数,也是从全局范围执行回调。无论如何,请参阅第一句话。
另请参阅上面的注释Example #2 Dynamically accessing namespaced elements,其中说明了
必须使用完全限定名称(带名称空间前缀的类名)。
答案 1 :(得分:1)
在当前版本的PHP中,你拥有它的方式就是这样 - 当使用字符串引用类名时,它需要完全限定它的完整命名空间。这不是很好,但就是这样。
在即将发布的PHP v5.5中,它们将包含一个通过提供新的Classname::class
语法来解决此问题的功能,您可以使用该语法而不是将FQN类名放在字符串中。
有关此内容的更多信息,请参阅此处的相关PHP RFC页面:https://wiki.php.net/rfc/class_name_scalars
您的代码看起来像这样:
return call_user_func([models\$name::class,"getInstance"]);
这可能不准确;我没有5.5的副本来测试以确认。但无论哪种方式,新语法都会使像你这样的用例更好。