4

All examples below are based on the guarantee that all files exist in their correct location. I've treble checked this.

(1) This works when NOT using namespaces:

$a = "ClassName";
$b = new $a();

This doesn't work:

// 'class not found' error, even though file is there

namespace path\to\here;
$a = "ClassName";
$b = new $a();

This DOES work:

namespace path\to\here;
$a = "path\to\here\ClassName";
$b = new $a();

So it seems the namespace declaration is ignored when using a variable to instantiate a class.

Is there a better way (than my last example) so I don't need to go through some code and change every variable to include the namespace?

3
  • Namespace declarations normally go once at the top of the source file, not in front of the variable you need it for. Commented Oct 28, 2013 at 18:10
  • Best you can do is alter your variable namespace using the __namespace__ keyword like $a = __namespace__ . "\\ClassName";. Doesn't solve the problem but at least now if your namespace changes, so will the code. Commented Oct 28, 2013 at 18:15
  • Thanks to all for comments and answers. I actually think the last comment above is the best way to do it (unless calling namespace has performance issues, which I doubt). Thanks again for both answers, I've upvoted both. My accepted answer is the last comment above. Commented Oct 29, 2013 at 7:41

2 Answers 2

5

The namespace is always part of the complete class name. With some use statements you'll only create an alias for a class during runtime.

<?php

use Name\Space\Class;

// actually reads like

use Name\Space\Class as Class;

?>

The namespace declaration before a class only tells the PHP parser that this class belongs to that namespace, for instantiation you still need to reference the complete class name (which includes the namespace as explained before).

To answer your specific question, no, there isn't any better way than the last example included in your question. Although I'd escape those bad backslashes in a double quoted string.*

<?php

$foo = "Name\\Space\\Class";
new $foo();

// Of course we can mimic PHP's alias behaviour.

$namespace = "Name\\Space\\";

$foo = "{$namespace}Foo";
$bar = "{$namespace}Bar";

new $foo();
new $bar();

?>

*) No need for escaping if you use single quoted strings.

Sign up to request clarification or add additional context in comments.

Comments

1

When storing a class name in a string, you need to store the full class name, not only the name relative to the current namespace:

<?php
// global namespace
namespace {
    class Outside {}
}

// Foo namespace
namespace Foo {
    class Foo {}

    $class = "Outside";
    new $class; // works, is the same as doing:
    new \Outside; // works too, calling Outside from global namespace.

    $class = "Foo";
    new $class; // won't work; it's the same as doing:
    new \Foo; // trying to call the Foo class in the global namespace, which doesn't exist

    $class  = "Foo\Foo"; // full class name
    $class  = __NAMESPACE__ . "\Foo"; // as pointed in the comments. same as above.
    new $class; // this will work.
    new Foo; // this will work too.
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.