PHP:具有不完全限定名称空间的动态实例

时间:2011-05-27 10:04:34

标签: php namespaces

我想让我的班级做好准备:

use somedir\http as Http;

$S_bodyWriterType  = 'Http\\' . strtolower($S_requestBodyPayloadType) . '\\RequestBodyWriter';
$this->_O_requestBodyWriter = new $S_bodyWriterType;

它说这个课程不存在。然而,这将工作(这里没有涉及字符串):

$this->_O_requestBodyWriter = new Http\xml\RequestBodyWriter;

这当然也会起作用(命名空间是完全限定的):

$S_bodyWriterType  = 'somedir\http\\' . strtolower($S_requestBodyPayloadType) . '\\' . 'RequestBodyWriter';
$this->_O_requestBodyWriter = new $S_bodyWriterType;

我绝对更喜欢使用缩短的命名空间,而不必在代码库的不同位置编写长的,完全限定的命名空间,并且必须在目录位置移动时更改它们。我已经把头发拉了一段时间了。

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

好的,你自己提供了Bug report;)但事实如下:如果你在一个字符串中定义一个类名,而不是说,该对象是在同一个上下文中创建的。

namespace y {
  use a\b as B;
  $GLOBALS['class'] = 'B\\MyClass';
}
namespace z {
  use k\l as B;
  $classname = $GLOBALS['class'];
  $a = new $classname;
}

因此,您需要在完全限定的字符串中定义类名。我建议使用(namespace- / class-)常量

use a\b as B;
const NAMESPACE_B = '\\a\\b';
$classname = NAMESPACE_B . '\\MyClass';

如果要实例化的类在子名称空间中,请记住,伪常量__NAMESPACE__始终存在;

namespace a;
use a\b as B;
$classname = __NAMESPACE__ . '\\b\\MyClass';

在您的情况下,我建议创建一个工厂

use somedir\http as Http;
class RequestBodyWriterFactory {
  public function create($type) {
    $classname = __NAMESPACE__ . "\\$type\\RequestBodyWriter";
    return new $classname;
  }
}

// somewere else
$this->_O_requestBodyWriter = $this->factory->create(strtolower($S_requestBodyPayloadType));

通过这种方式,您可以更好地控制创建的内容及其创建方式。