Object Creation From Class Name Not Working Within Namespace
I'm creating a factory class in my project, where this class gets a Report Type as a string. This string has the name of the concrete class that implements a Report Interface.
The issue I'm having is that when I'm instantiating this class, I get a Class not found
error.
Here follows the factory code.
namespace App\Term\Reports;
class Factory
{
public static function build($type)
{
$obj = new CableBySensor(); // Works!
// $type == 'CableBySensor'
$obj2 = new $type; // Class not found :(
// ... validates if the class exists ...
// ... and if it implements the Report Interface ...
// ... throw exception if class doesn't exist or doesn't implements interface
// ... then returns the corresponding object.
}
}
Both methods are virtually the same thing.
First: Why do I have to specify the full qualified name of the class in the string to make it work? The class CableBySensor
resides in the same namespace as Factory
.
This started giving me trouble because I also want to validate that the class being instantiated implements a ReportsInterface
.
Second: How do I overcome this? Should I call the factory like this $myReport = Factory::build('App\Term\Reports\' . $className);
or should I use the __NAMESPACE__
constant inside the Factory class such as this: $obj = new __NAMESPACE__ . '\' . $className
?
Thank you.
Answer
Indifferently whether the factory approach is useful here or not, the problem is with trying to instantiate from a dynamic variable.
Or as akhoondi at php.net pointed out:
One must note that when using a dynamic class name [...] the "current namespace" [...] is global namespace.
There are possibly 3 solutions:
pass the fully qualified class name to your factory method (arghh...)
$instance = Factory::build('Acme\CableBySensor');
Or, do a check in your build method and prefix the namespace if necessary (as suggested here) (sounds not so fool proof to me)
public static function build($type) { if ($type[0] !== '\\') { $type = '\\' . __NAMESPACE__ . '\\' . $type; } $obj = new $type; ... }
Or, if you have PHP 5.5+ why not use class name resolution via ::class? Personally, I would go for that one whenever possible:
$instance = Factory::build(CableBySensor::class);
Related Questions
- → "failed to open stream" error when executing "migrate:make"
- → October CMS Plugin Routes.php not registering
- → OctoberCMS Migrate Table
- → OctoberCMS Rain User plugin not working or redirecting
- → October CMS Custom Mail Layout
- → October CMS - How to correctly route
- → October CMS create a multi select Form field
- → October CMS - Conditionally Load a Different Page
- → How to disable assets combining on development in OctoberCMS
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → OctoberCms component: How to display all ID(items) instead of sorting only one ID?
- → In OctoberCMS how do you find the hint path?
- → How to register middlewares in OctoberCMS plugin?