我正在我的项目中创建一个工厂类,其中此类将报告类型作为字符串。此字符串具有实现报告接口的具体类的名称。
我遇到的问题是,当我实例化此类时,我收到Class not found
错误。
以下是工厂代码。
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.
}
}
两种方法几乎都是一样的。
首先:为什么我必须在字符串中指定类的完全限定名称才能使其正常工作?类CableBySensor
与Factory
位于同一名称空间。
这开始给我带来麻烦,因为我还想验证正在实例化的类是否实现了ReportsInterface
。
第二:我如何克服这个问题?我应该像这样$myReport = Factory::build('App\Term\Reports\' . $className);
调用工厂,还是应该在Factory类中使用__NAMESPACE__
常量,例如:$obj = new __NAMESPACE__ . '\' . $className
?
谢谢。
答案 0 :(得分:2)
无论工厂方法在这里是否有用,无论如何 问题在于尝试从动态变量实例化。
必须注意的是,当使用动态类名[...]时,“当前命名空间”[...]是全局命名空间。
可能有3个解决方案:
将完全限定的类名传递给工厂方法(arghh ...)
$instance = Factory::build('Acme\CableBySensor');
或者,检查你的构建方法并在必要时为命名空间添加前缀(如建议here)(听起来不是那么简单)
public static function build($type)
{
if ($type[0] !== '\\') {
$type = '\\' . __NAMESPACE__ . '\\' . $type;
}
$obj = new $type;
...
}
或者,如果你有 PHP 5.5 + ,为什么不使用class name resolution via ::class? 就个人而言,我会尽可能选择那个:
$instance = Factory::build(CableBySensor::class);