Doctrine2有一个内置类型'数组',我发现它对我的项目有用。它完美适用于标量类型的数组。但现在我想使用一个对象数组。像这样:
/**
* @ORM\Entity
*/
class MyEntity {
/**
* @var MyEntityParameter[] array of MyEntityParameter instances
*
* @ORM\Column(name="parameters", type="array", nullable=true)
*
*/
private $parameters;
}
MyEntityParameter是一个可以序列化的类。我也在Symfony的表单生成器中使用它。
我的计划完美无缺,但是当MyEntityParameter实例中的字段发生更改时,Doctrine不检测它,因此不会更新记录。如果我删除或添加数组元素,Doctrine会检测到。我意识到发生这种情况是因为当我更改其字段时类实例对象id不会改变,但是我怎样才能使Doctrine检测到这种改变?
答案 0 :(得分:1)
我为我找到了一个有效的解决方案。我认为这不是那么优雅,但如果没有好方法可以解决这个问题,它可以为我和其他人工作。
首先,我决定不在数组中保留对象,而是保留数组。但是,我仍然希望在Symfony的表单构建器中使用MyEntityParameter
类。在这种情况下,我们的想法是禁用我们的字段映射:
在表单构建器中,我们执行以下操作:
// Acme/Bundle/DemoBundle/Form/Type/MyEntityType.php
// ...
class MyEntityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('parameters', 'collection', array(
'mapped' => false, // do not map this field
'type' => new MyEntityParameterType(),
// ... other options ...
));
}
}
在子类型(MyEntityParameterType
)中,我们将'data_class'设置为MyEntityParameter
(我没有显示代码,因为它与问题无关)。
现在我们只需要手动填充和处理这个未映射字段的数据。
在控制器中:
public function editAction($id, Request $request)
{
// ...
// $object is an instance of MyEntity
$form = $this->createForm(new MyEntityType(), $object);
$parameters = $object->getParameters();
if ($parameters) {
foreach ($parameters as $key => $parameter)
{
$form->get('parameters')->add($key, new MyEntityParameterType(),
array(
// here I assume that the constructor of MyEntityParameter
// accepts the field data in an array format
'data' => new MyEntityParameter($parameter),
)
);
}
}
if ($request->isMethod('POST')) {
$form->submit($request);
$parameters = array();
foreach ($form->get('parameters')->all() as $parameter) {
// here first getData() gives MyEntityParameter instance
// and the second getData() is just a method of MyEntityParameter
// that returns all the fields in an array format
$parameters[] = $parameter->getData()->getData();
}
$object->setParameters($parameters);
// if the parameters were changed in the form,
// this change will be detected by UnitOfWork
}
// ...
}
答案 1 :(得分:0)
我记得之前遇到过这个问题,并且对我有用的解决方法是设置一个新对象,以便Doctrine能够识别实体属性已被修改,然后设置具有您想要持久更改的对象。
$parameters = $entity->getParameters();
$parameters->foo = "bar";
$entity->setParameters(new MyEntityParameter());
$entity->setParameters($parameters);
$em->persist($entity);
如果它是MyEntityParameter
个实例的数组,则以下代码可能有效。
$parameters = $entity->getParameters();
$parameters[3]->foo = "bar"; // Just an example
$entity->setParameters(array(new MyEntityParameter()));
$entity->setParameters($parameters);
$em->persist($entity);