开发者

PHP : dynamic instance with not fully-qualified namespaces

开发者 https://www.devze.com 2023-03-08 14:58 出处:网络
I\'d like to instanciate my class doing : use somedir\\http as Http; $S_bodyWriterType= \'Http\\\\\' . strtolower($S_requestBodyPayloadType) . \'\\\\RequestBodyWriter\';

I'd like to instanciate my class doing :

use somedir\http as Http;

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

It says the class does not exist. However THAT would work (no string involved here) :

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

And that would also work of course (the namespace is fully qu开发者_运维问答alified) :

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

i'd definitely prefer to use shortened namespaces instead of having to write long, fully-qualified namespaces in different places of the codebase and having to change them all in case the directory location moves. I've been pulling my hair off for a while now over this.

Thanks for help !


OK, you provided the Bug report yourself ;) But thats the fact: If you define a classname in a string, its not said, that the object is created in the same context.

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

Thus you need to define classnames in string full qualifed. I suggest to use (namespace-/class-)constants

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

If the class you want to instanciate is in a subnamespace, remember, that the pseudo-constant __NAMESPACE__ always exists;

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

Additional in your case I suggest to create a factory

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

This way you have more control on what is created and how its created.

0

精彩评论

暂无评论...
验证码 换一张
取 消