ken
ken

Reputation: 9013

Dynamic loading of classes can't address namespace/use

I have noticed that when I am using namespacing that loading classes dynamically doesn't work the same as when I'm loading them statically. So, for instance, without the use of namespaces the following are equivalent in their action of instantiating a class called FooBar:

$foobar = new FooBar();

and

$classname = "FooBar";
$foobar = new $classname;

However if when using namespacing I have some code like this:

<?php

namespace Structure\Library;

$foobar = new UserService();
$classname = "UserService";
$barfoo = new $classname;

In this case the UserService class's fully qualified name is Structure\Library\UserService and if I use the fully qualified name it works in both cases but if I use just the shortcut name of 'UserService' it only works when instantiated with the static method. Is there a way to get it to work for both?

P.S. I am using an autoloader for all classes ... but I'm assuming that the problem is happening before the autoloader and is effecting the class string that is passed to the autoloader.

Upvotes: 15

Views: 11479

Answers (3)

Pancho
Pancho

Reputation: 2193

The following dynamically instantiates $barfoo as a Structure\Library\UserService object:

namespace Structure\Library;

$classname = __NAMESPACE__ . "\\" . "UserService";
$barfoo = new $classname;

Upvotes: 0

cartbeforehorse
cartbeforehorse

Reputation: 3487

I think this is a case of reading the documentation. See example 3:

http://php.net/manual/en/language.namespaces.importing.php

Seems to confirm my earlier comment.

<?php
    namespace foo\bar;

    $classStr = "myClass";    
    $nsClass = "\\foo\\bar\\myClass";

    $x = new myClass;    // instantiates foo\bar\myClass, because of declared namespace at top of file
    $y = new $classStr;  // instantiates \myClass, ignoring declared namespace at top of file
    $z = new $nsClass    // instantiates foo\bar\myClass, because it's an absolute reference!
?>

Upvotes: 13

user1467267
user1467267

Reputation:

This would be the nearest solution I can find:

define('__NSNAME__', __NAMESPACE__.'\\');

$foobar = new UserService();
$classname = __NSNAME__."UserService";
$barfoo = new $classname;

Good luck!

Update 1

This might be good for further reading: http://www.php.net/manual/en/language.namespaces.importing.php

use My\Full\UserService as UserService;

Update 2

This is how far I got now:

namespace Structure\Library\Home;

class UserService {

}

namespace Structure\Library;

use Structure\Library\Home\UserService as UserService;

define('UserService', __NAMESPACE__.'\\Home\\UserService', TRUE);

$foobar = new UserService();
$classname = UserService;
$barfoo = new $classname;

Or this variant for more flexibility:

define('Home', __NAMESPACE__.'\\Home\\', TRUE);

$foobar = new UserService();
$classname = Home.'UserService';
$barfoo = new $classname;

Docs

Upvotes: 5

Related Questions