我正在我的项目中创建一个工厂类,其中该类以字符串形式获取报告类型。此字符串具有实现报表接口的具体类的名称。
我遇到的问题是,当我实例化这个类时,我收到一个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
?
谢谢。
无动于衷地对待工厂方法在这里是否有用,问题在于尝试从动态变量实例化。
或者正如 php.net 的akhoondi指出的那样:
必须注意的是,当使用动态类名时,"当前命名空间"[...]是全局命名空间。
可能有 3 种解决方案:
-
将完全限定的类名传递给工厂方法(啊...
$instance = Factory::build('Acme'CableBySensor');
-
或者,检查您的构建方法并在必要时为命名空间添加前缀(如此处建议)(对我来说听起来不是那么万无一失)
public static function build($type) { if ($type[0] !== '''') { $type = '''' . __NAMESPACE__ . '''' . $type; } $obj = new $type; ... }
-
或者,如果你有PHP 5.5+,为什么不通过::class使用类名解析?就个人而言,我会尽可能选择那个:
$instance = Factory::build(CableBySensor::class);