短篇小说(编辑)
可以存储数组而不是映射关联。在 Symfony2 中,使用集合 Field Type相当容易。例如,使用此技术,您可以存储填充数组事件字段的文本字段数组。但是,要更新数组,有一个技巧,@Vadim Ashikhman 在接受的答案中很好地解释了这个技巧。
很长的故事
有时存储数组而不是映射关联更有用且更有效。但是,一旦创建,如果该数组的大小没有改变,更新这个数组仍然很复杂?
许多人有类似的问题,但没有人找到解决此问题的适当方法。
一个团队可以组织许多活动。这些事件使用 Doctrine 而不是使用 OneToMany 关联简单地存储在一个数组中。因此,实体 Event 没有与 Doctrine 映射。
实体事件(未映射到 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;
}
}
实体团队
<?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;
}
活动形式
<?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,
));
}
...
}
团队形式
<?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',
));
}
...
}
控制器
/**
* 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,
);
}