在命名空间中调用另一个类名时找不到类



当我动态创建一个类对象时,我不明白为什么它抛出未找到的类。然而,如果我将删除命名空间App\Controls使用App\Control\one,则它可以完美地工作示例代码:

namespace AppControls;
use AppControlsone;

class one {
public static function test_one($className, $object) {
return $object((new $className));
}
}
class two {
public function language($lang) {
echo 'I love '.$lang;
}
}

one::test_one('two', function($table) {
$table->language('PHP');
});

从这个结构中,我想调用类2,这取决于我输入的值。我还包括使用App\Controls\two,但仍然不起作用,但事实并非如此,因为我不会添加另一个。使用App\Cntrols\className只是为了调用创建另一个类对象,这在PHP中是不可能的。

在PHP中,名称空间是在编译代码时解析的,而不是在运行时解析的。

所以,当你写这篇文章时:

namespace MyNamespace;
use MyOthernamespaceSomeClass;
$foo = new Foo;
$bar = new SomeClass;

编译器查看当前的名称空间,以及您所拥有的类名";导入";,并像你写的那样编译代码:

$foo = new MyNamespaceFoo;
$bar = new MyOthernamespaceSomeClass;

(请注意,不需要use当前命名空间中的任何内容;这被假定为所有内容的默认前缀。(

在您的代码中,编译器不知道'two'将被用作类名,所以它不会更改它;因此,当动态代码运行时,它的字面意思是:

return $object((new two));

这不起作用——没有一个类叫two,只有一个叫AppControlstwo

解决这个问题的方法是神奇的::class语法,它告诉编译器像扩展类名一样扩展一些内容,然后将其转换为字符串。重要的是要知道,尽管有这个名字,它实际上并不在乎它扩展的东西是一个类,还是存在,它只是扩展它,并假设你知道你在用它做什么。

所以如果你写这个:

namespace AppControls;
one::test_one(two::class, function($table) {
$table->language('PHP');
});

它将由编译器扩展为:

AppControlsone::test_one('AppControlstwo', function($table) {
$table->language('PHP');
});

然后,当它进入动态代码时,它将引用正确的类名,并像这样运行代码:

return $object((new AppControlstwo));

最新更新