1

Doctrine2 有一个内置类型“数组”,我发现它对我的项目很有用。它完美地适用于标量类型的数组。但现在我想使用一个对象数组。像这样的东西:

/**
 * @ORM\Entity
 */
class MyEntity {

    /**
     * @var MyEntityParameter[] array of MyEntityParameter instances
     *
     * @ORM\Column(name="parameters", type="array", nullable=true)
     *
     */
    private $parameters;

}

其中 MyEntityParameter 是一个可以序列化的类。我也在 Symfony 的 Form Builder 中使用它。

我的计划完美运行,除了当 MyEntityParameter 实例中的字段发生更改时,Doctrine 没有检测到它,因此不会更新记录。如果我删除或添加数组元素,Doctrine 会检测到这一点。我意识到发生这种情况是因为当我更改其字段时类实例对象 id 不会更改,但是我怎样才能使 Doctrine 检测到这种更改呢?

4

2 回答 2

1

我为我找到了一个可行的解决方案。我不认为它那么优雅,但如果没有解决这个问题的好方法,它可以为我和其他人工作。

首先,我决定不在数组中保留对象,而是保留数组。然而,我仍然想MyEntityParameter在 Symfony 的表单构建器中使用类。在这种情况下,我们的想法是禁用我们字段的映射:

在表单构建器中,我们执行以下操作:

// 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
    }

    // ...
}
于 2013-11-03T20:16:14.150 回答
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);
于 2013-11-03T19:22:36.510 回答