'Class not found when calling another class name in namespace
When I create a class object dynamically I don't understand why it throws class not found. However, if I will remove namespace App\Controls and use App\Controls\one, it worked perfectly example code:
namespace App\Controls;
use App\Controls\one;
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');
});
from this structure I want to call class two depends on the value I input. I also include use App\Controls\two but still not working, but that's not the case because supposedly I will not add another use App\Controls\className just to call create another class object and it's not possible from PHP.
Solution 1:[1]
In PHP, namespaces are resolved when the code is compiled, not when it is run.
So, when you write this:
namespace MyNamespace;
use MyOthernamespace\SomeClass;
$foo = new Foo;
$bar = new SomeClass;
The compiler looks at the current namespace, and the class names you've "imported", and compiles the code as though you'd written this:
$foo = new MyNamespace\Foo;
$bar = new MyOthernamespace\SomeClass;
(Note that you don't need to use anything in the current namespace; that's assumed as the default prefix for everything.)
In your code, the compiler doesn't know that the 'two' is going to be used as a class name, so it doesn't change it; so when the dynamic code runs, it comes out literally as:
return $object((new two));
Which won't work - there isn't a class called two, only one called App\Controls\two.
The solution to this is the magic ::class syntax, which tells the compiler to expand something like it would for a class name, and then turn it into a string. It's important to know that despite the name, it doesn't actually care if the thing it's expanding is a class, or exists at all, it just expands it and assumes you know what you're doing with it.
So if you write this:
namespace App\Controls;
one::test_one(two::class, function($table) {
$table->language('PHP');
});
It will be expanded by the compiler to this:
App\Controls\one::test_one('App\Controls\two', function($table) {
$table->language('PHP');
});
Then when it gets into the dynamic code, it will be referencing the right class name, and run the code as though it was this:
return $object((new App\Controls\two));
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | IMSoP |
