Php 从类名创建对象在命名空间内不起作用
我正在我的项目中创建一个factory类,该类以字符串形式获取报告类型。此字符串具有实现报表接口的具体类的名称 我遇到的问题是,当我实例化这个类时,我得到一个Php 从类名创建对象在命名空间内不起作用,php,oop,laravel,Php,Oop,Laravel,我正在我的项目中创建一个factory类,该类以字符串形式获取报告类型。此字符串具有实现报表接口的具体类的名称 我遇到的问题是,当我实例化这个类时,我得到一个类未找到错误 以下是工厂代码 namespace App\Term\Reports; class Factory { public static function build($type) { $obj = new CableBySensor(); // Works! // $type
类未找到
错误
以下是工厂代码
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)
或者我应该在工厂类中使用\uu名称空间\uu
常量,例如:$obj=new\uu名称空间\uuu.'\'$类名
谢谢。不管工厂方法在这里是否有用, 问题在于试图从动态变量实例化 或者正如所指出的: 必须注意,当使用动态类名[…]时,“当前名称空间”[…]是全局名称空间 可能有3种解决方案:
- 将完全限定的类名传递给工厂方法(arghh…)
- 或者,检查您的构建方法,并在必要时为名称空间添加前缀(如建议的那样)(对我来说听起来不是那么简单)
- 或者,如果您有PHP5.5+为什么不使用?
就我个人而言,只要有可能,我都会选择:
$instance = Factory::build(CableBySensor::class);
$type
作为字符串传递?此外,您是否会考虑使用开关($type){case“CableBySensor”:$obj2=new CableBySensor();break;}
。您是否尝试过使用名称空间来查看它是否有效?我建议您在线阅读有关参数化工厂模式的内容。我个人不会写一个工厂类,然后像你们一样使用它。大家好,谢谢你们的评论。我一直在关注这件事@Halcyon只是我认为每次我有一个新的报告类型时,我都必须修改工厂并在switch语句中添加一个case
。按照我的方式,它可以与实现接口的任何类一起工作(或者我认为是D)。我将验证该类是否实现了报表接口。-@YehiaAwad使用名称空间工作@我会的,谢谢你!我不完全确定这篇文章的作者是否理解如何使用工厂。这对我来说似乎非常可怕:“工厂能够创建不同类型的对象,而不一定知道实际创建的对象是什么类型的。”。通常情况下,如果实例化对象很复杂,或者需要将不希望传递的依赖项传递给需要创建实例的对象,那么您会使用工厂(因此,您会给它一个“抽象”工厂)。回答第一个问题。大约在第二天。我同意第二种,不过稍微调整一下。尽管我很想使用第三个选项,但在这一点上,我只有一个名为cable\u by\u sensor
(这是用户选择的选项)的字符串。因此,我将studly_case()
应用于$type
(然后作为惯例,我有实际的类名)。在这之后,我在前面添加\uuuu名称空间\uuuu
,然后验证类是否实现了我想要的接口,然后返回一个新的对象实例或抛出异常的元素。
public static function build($type)
{
if ($type[0] !== '\\') {
$type = '\\' . __NAMESPACE__ . '\\' . $type;
}
$obj = new $type;
...
}
$instance = Factory::build(CableBySensor::class);