在 ZF2 中使用 Doctrine 模块水化器和表单注释
Using Doctrine module hydrator and form annotations in ZF2
我需要一些建议。我在一个 ZF2 项目中使用 Doctrine 2 和 Doctrine Orm 模块。
我使用 doctrine 模块提供的服务处理身份验证。结果是,在身份验证之后,我在我的身份验证服务中拥有身份(由 getIdentity() 方法返回),它是我的用户实体的一个实例。
我有两个实体:用户和组。在用户实体中定义了多对一关系与组(一个用户属于一个组,一个组有很多用户)。基本的东西。
当连接的用户需要在 CRUD 中编辑它自己的组时,我的问题就来了。
我处理 CRUD 的方式很简单:我在我的实体的注释中定义了我的表单,我指定了 Doctrine Hydrator 并使用了 Doctrine 对象 Select。除了编辑自己的组之外,一切都完美无缺。
我的理解是:由于我的多对一关系是lazy loading fetch模式,经过身份验证后,doctrine的身份映射包含用户组作为代理的实例。当用户到达编辑操作时,会发生以下情况:
/*
Code that get the goup id to edit from request
*/
if (!empty($id)) {
$entity = $groupRepository->find($id);
}
$builder = new AnnotationBuilder();
$this->form = $builder->createForm($entity);
结果是,当编辑任何不在学说身份图中的组作为代理实例时,一切正常。但是,如果我需要编辑的实体已经作为代理实例存在于身份映射中,那么表单工厂无法找到我的实体中定义的注释,它就会中断。
也许我的方式是一种不好的做法?我想使用注释来构建我的表单。
我能找到的唯一解决方法(我猜这是一种糟糕的方法)是像这样更改我的代码:
/*
Code that get the goup id to edit from request
*/
if (!empty($id)) {
$em->clear(); <== NEW LINE HERE
$entity = $groupRepository->find($id);
}
$builder = new AnnotationBuilder();
$this->form = $builder->createForm($entity);
理论上,调用 clear() 以分离所有实体在我的用例中应该不是问题,因为我知道我只想编辑组实体,但我想这可能不正确做。
另一个解决方案(但尚未尝试):创建一个自定义的 FormFactory,我将其传递给我的 AnnotationBuilder。然后,此自定义 FormFactory 将在从注释启动表单创建之前检测实体的类型。如果它是一个代理那么它应该得到 "real" class 的注解而不是 ?
或者我错过了一些更简单的东西?
当您通过代理时,这不能正常工作,我有点惊讶,但我同意您当前的解决方案很糟糕 :)。您可以像这样以不同的方式解决它:
// collect the class from the entity or proxy
$className = \Doctrine\Common\Util\ClassUtils::getClass($entity);
$builder = new AnnotationBuilder();
$this->form = $builder->createForm($className);
注释生成器在传递 class 名称时运行良好。上面的代码从代理对象和实体中收集真实的 class 名称,因此这对这两种情况都有效。
但我仍然建议检查您的配置,因为我几乎可以肯定它也应该与代理一起正常工作。
我需要一些建议。我在一个 ZF2 项目中使用 Doctrine 2 和 Doctrine Orm 模块。 我使用 doctrine 模块提供的服务处理身份验证。结果是,在身份验证之后,我在我的身份验证服务中拥有身份(由 getIdentity() 方法返回),它是我的用户实体的一个实例。
我有两个实体:用户和组。在用户实体中定义了多对一关系与组(一个用户属于一个组,一个组有很多用户)。基本的东西。
当连接的用户需要在 CRUD 中编辑它自己的组时,我的问题就来了。
我处理 CRUD 的方式很简单:我在我的实体的注释中定义了我的表单,我指定了 Doctrine Hydrator 并使用了 Doctrine 对象 Select。除了编辑自己的组之外,一切都完美无缺。
我的理解是:由于我的多对一关系是lazy loading fetch模式,经过身份验证后,doctrine的身份映射包含用户组作为代理的实例。当用户到达编辑操作时,会发生以下情况:
/*
Code that get the goup id to edit from request
*/
if (!empty($id)) {
$entity = $groupRepository->find($id);
}
$builder = new AnnotationBuilder();
$this->form = $builder->createForm($entity);
结果是,当编辑任何不在学说身份图中的组作为代理实例时,一切正常。但是,如果我需要编辑的实体已经作为代理实例存在于身份映射中,那么表单工厂无法找到我的实体中定义的注释,它就会中断。 也许我的方式是一种不好的做法?我想使用注释来构建我的表单。
我能找到的唯一解决方法(我猜这是一种糟糕的方法)是像这样更改我的代码:
/*
Code that get the goup id to edit from request
*/
if (!empty($id)) {
$em->clear(); <== NEW LINE HERE
$entity = $groupRepository->find($id);
}
$builder = new AnnotationBuilder();
$this->form = $builder->createForm($entity);
理论上,调用 clear() 以分离所有实体在我的用例中应该不是问题,因为我知道我只想编辑组实体,但我想这可能不正确做。
另一个解决方案(但尚未尝试):创建一个自定义的 FormFactory,我将其传递给我的 AnnotationBuilder。然后,此自定义 FormFactory 将在从注释启动表单创建之前检测实体的类型。如果它是一个代理那么它应该得到 "real" class 的注解而不是 ?
或者我错过了一些更简单的东西?
当您通过代理时,这不能正常工作,我有点惊讶,但我同意您当前的解决方案很糟糕 :)。您可以像这样以不同的方式解决它:
// collect the class from the entity or proxy
$className = \Doctrine\Common\Util\ClassUtils::getClass($entity);
$builder = new AnnotationBuilder();
$this->form = $builder->createForm($className);
注释生成器在传递 class 名称时运行良好。上面的代码从代理对象和实体中收集真实的 class 名称,因此这对这两种情况都有效。
但我仍然建议检查您的配置,因为我几乎可以肯定它也应该与代理一起正常工作。