Doctrine不更新一个简单的数组类型字段 [英] Doctrine does not update a simple array type field
问题描述
短篇小说(编辑)
可以存储数组而不是映射关联。在Symfony2中,使用
参考:
Doctrine使用相同的运算符
===
来比较旧
和新价值观。与
不同数据的同一对象使用的运算符始终返回true。有另一种方法来解决
这个问题,你可以克隆需要更改的对象。$ items = $ myEntityObject-> getItems();
$ items [0] = clone $ items [0];
$ items [0] - > setSomething(123);
$ myEntityObject-> setItems($ items);
或更改setItems()方法
public function setItems($ items)
{
if(!empty($ items)&& $ items === $ this-> items) {
重置($ items);
$ key = key($ items);
$ items [$ key] = clone $ items [$ key];
}
$ this-> items = $ items;
}
Short Story (Edit)
It is possible to store an array instead of a mapped association. In Symfony2, this is fairly easy using the collection Field Type. For example, using this technique, you could store an array of text fields that populate an array events field. However, to update an array, there is a trick, and this trick is beautifully explained by @Vadim Ashikhman in the accepted answer.
Long Story
Sometimes it is useful and more efficient to store an array instead of a mapped association. However, once created, it remains complicated to update this Array if the size of that array does not change?
Many people have a similar issue but nobody found a proper solution to this problem.
A team can organise many events. These events are simply stored within an array using Doctrine instead of using a OneToMany association. Therefore, the entity Event is not mapped with Doctrine.
Entity Event (not mapped with Doctrine)
<?php
namespace Acme\TestBundle\Entity;
...
class Event
{
/**
* @Assert\NotBlank
*/
private $name;
public function setName($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}
Entity Team
<?php
namespace Acme\TestBundle\Entity;
...
/**
* @ORM\Entity()
* @ORM\HasLifecycleCallbacks
* @ORM\Table(name="teams")
*/
class Team
{
/**
* @ORM\Column(type="array")
* @var array
*/
protected $events;
public function addEvent($event)
{
if (!in_array($event, $this->events, true)) {
$this->events[] = $event;
}
return $this;
}
public function removeEvent($event)
{
if (false !== $key = array_search($event, $this->events, true)) {
unset($this->events[$key]);
$this->events = array_values($this->events);
}
return $this;
}
public function getEvents()
{
return $this->events;
}
public function setEvents(array $events)
{
$this->events = array();
foreach ($events as $event) {
$this->addEvent($event);
}
return $this;
}
Event Form
<?php
namespace Acme\TestBundle\Form\Type;
...
class EventType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->add('name', 'text');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\TestBundle\Entity\Event',
'cascade_validation' => true,
));
}
...
}
Team Form
<?php
namespace Acme\TestBundle\Form\Type;
...
class TeamType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->add('events','collection', array(
'type' => new EventType(),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'by_reference' => false,
'options' => array('data_class' => 'Acme\TestBundle\Entity\Event'),
)
);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\TestBundle\Entity\Team',
));
}
...
}
The Controller
/**
* Update a team
*
* @Route("update/{team_id}", name="updateTeamFromId")
* @Template("AcmeTestBundle:Team:teamUpdate.html.twig")
*/
public function updateTeamAction($team_id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$repository= $em->getRepository('AcmeTestBundle:Team');
$team_to_update = $repository->find($team_id);
$form = $this->createForm(new teamType(), $team_to_update);
if ($request->getMethod() == 'POST')
{
$form->bind($request);
if ($form->isValid()){
$em->persist($team_to_update);
$em->flush();
return $this->redirect($this->generateUrl('homepage')) ;
}
}
return array(
'form' => $form->createView(),
'team_id' => $team_id,
);
}
You can find the answer here:
How to force Doctrine to update array type fields?
Refs:
Doctrine uses identical operator
===
to compare changes between old and new values. The operator used on the same object with different data always return true. There is the other way to solve this issue, you can clone an object that needs to be changed.$items = $myEntityObject->getItems(); $items[0] = clone $items[0]; $items[0]->setSomething(123); $myEntityObject->setItems($items);
Or change the setItems() method
public function setItems($items) { if (!empty($items) && $items === $this->items) { reset($items); $key = key($items); $items[$key] = clone $items[$key]; } $this->items = $items; }
这篇关于Doctrine不更新一个简单的数组类型字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!