Doctrine orm Doctrine2:如何使用数组类型中的对象数组?

Doctrine orm Doctrine2:如何使用数组类型中的对象数组?,doctrine-orm,Doctrine Orm,Doctrine2有一个内置类型“array”,我发现它对我的项目很有用。它可以完美地处理标量类型的数组。但是现在我想使用一个对象数组。大概是这样的: /** * @ORM\Entity */ class MyEntity { /** * @var MyEntityParameter[] array of MyEntityParameter instances * * @ORM\Column(name="parameters", type="array

Doctrine2有一个内置类型“array”,我发现它对我的项目很有用。它可以完美地处理标量类型的数组。但是现在我想使用一个对象数组。大概是这样的:

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

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

}
其中MyEntityParameter是一个可以序列化的类。我还在Symfony的表单生成器中使用它


我的计划运行得很好,只是当MyEntityParameter实例中的字段发生更改时,Doctrine不会检测到它,因此不会更新记录。如果我删除或添加数组元素,条令会检测到。我意识到这是因为当我更改类实例对象的字段时,类实例对象id不会更改,但我如何才能使它使Doctrine检测到此更改?

我记得以前遇到过这个问题,一个对我有效的解决方法是设置一个新对象,以便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);

我记得以前遇到过这个问题,一个对我有效的解决方法是设置一个新对象,这样条令可以识别已修改的实体属性,然后设置具有所需更改的对象

$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);

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

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

在form builder中,我们执行以下操作:

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

    // ...
}

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

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

在form builder中,我们执行以下操作:

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

    // ...
}

只是想确认一下,
$parameters
MyEntityParameter
的一个实例,还是
MyEntityParameter
的一个
数组?它是MyEntityParameter的一个实例数组,我会在问题中澄清这一点。很酷,我编辑了我的答案来解决这两种情况。必须确认,
$parameters
MyEntityParameter
的实例还是
MyEntityParameter
的实例数组?是MyEntityParameter的实例数组,我会在问题中澄清这一点。酷,我编辑了我的答案来解决这两种情况我检查了你的解决方案,但不幸的是,这对我不起作用。而且,老实说,我不认为条令跟踪这一设定呼叫。相反,UnitOfWork计算变更集,但它不会因为数组元素没有更改而更改(没有新建或删除,也没有更改数组中对象的spl\u object\u hash())。您可以调用persist方法两次,以便重新计算UnitOfWork变更集,甚至可以直接调用
$em->getUnitOfWork()->重新计算SingleEntityChangeSet()
,尽管这听起来有点老套。不幸的是,重新计算也不会起作用,因为没有什么可重新计算的(如果对象的散列相同,并且对象本身不是可由doctrine跟踪的,则doctrine不会识别对象更改。我检查了您的解决方案,但不幸的是,它对我不起作用。老实说,我认为doctrine不会跟踪此集合调用。相反,UnitOfWork计算更改集,但它不会更改,因为数组元素没有更改(没有新建或删除,数组中对象的spl_object_hash()没有更改)。这是一个棘手的问题。您可以调用persist方法两次,以便重新计算UnitOfWork更改集,甚至可以调用
$em->getUnitOfWork()->重新计算SingleEntityChangeSet()
直接,尽管这听起来有点老土。不幸的是,重新计算也不起作用,因为没有什么可以重新计算(如果对象的哈希相同,并且对象本身不是一个可由原则跟踪的对象,则原则不会识别对象更改)。