我有2个实体:医生& 时间表其中一位医生有很多时间表(OneToMany),许多时间表都有一位医生(ManyToOne)。我想从Doctor Create form Screen创建许多时间表。所以,我按照文章embedded form collection
一切都工作得很好,除了我正在让医生下载时间表创建会话,这意味着我只能为现有医生创建时间表。我知道医生下拉来自ManyToOne关系。
但就我而言,我需要为当前的医生(即将在屏幕上创建的医生)制定时间表,而不选择现有医生的下拉菜单。用伪代码告诉逻辑我想要什么:
//Doctor Create Action
public function createAction(Request $request)
{
$entity = new Doctor();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if ($form->isValid()) {
// Save(Persist) Doctor
// Grab Newly Created Doctor ID
// Create Timetables with that Doctor ID
// done
}
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
我已经阅读了所有类似的问题但没有解决方案。请大家帮我一些symfony初学者可以理解的例子。谢谢。
下面是表格结构&相关代码:
医生实体表
id INT PRIMARY KEY AUTO_INCREMENT
name VARCHAR(55)NOT NULL
时间表实体表
id INT PRIMARY KEY AUTO_INCREMENT
doctor_id INT (医生的外键)
clinic_id INT (诊所的外键)
_time VARCHAR(255)NOT NULL
医生实体班
<?php
namespace Nay\MMClinicsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Doctor
*
* @ORM\Table(name="doctors")
* @ORM\Entity(repositoryClass="Nay\MMClinicsBundle\Entity\DoctorRepository")
*/
class Doctor
{
/**
* @var ArrayCollection
*
* @ORM\OneToMany(targetEntity="Timetable", mappedBy="doctor", cascade={"persist"})
*/
public $timetables;
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="doctor_name", type="string", length=255)
*/
private $doctorName;
public function __construct(){
$this->timetables = new ArrayCollection();
}
/**
*get timetable of this doctor
* @return arraycollection
*/
public function getTimetables(){
return $this->timetables;
}
public function addTimetable(Timetable $t)
{
$this->timetables->add($t);
}
public function removeTimetable(Timetable $t)
{
$this->timetables->removeElement($t);
}
// **setters & getters for each property here**
}
时间表实体类
<?php
namespace Nay\MMClinicsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Timetable
*
* @ORM\Table(name="timetables")
* @ORM\Entity(repositoryClass="Nay\MMClinicsBundle\Entity\TimetableRepository")
*/
class Timetable
{
/**
* @var Clinic
*
* @ORM\ManyToOne(targetEntity="Clinic", inversedBy="timetables")
* @ORM\JoinColumn(name="clinic_id", referencedColumnName="id")
*/
public $clinic;
/**
* @var Doctor
*
* @ORM\ManyToOne(targetEntity="Doctor", inversedBy="timetables")
* @ORM\JoinColumn(name="doctor_id", referencedColumnName="id")
*/
public $doctor;
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var integer
*
* @ORM\Column(name="clinic_id", type="integer")
*/
private $clinicId;
/**
* @var integer
*
* @ORM\Column(name="doctor_id", type="integer")
*/
private $doctorId;
/**
* @var string
*
* @ORM\Column(name="_time", type="string", length=1024)
*/
private $time;
//**setters & getters for each property here**
}
医生表格类型
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('doctorName')
->add('timetables', 'collection', array('type' => new TimetableType(),'allow_add' => true ,'by_reference' => false, 'allow_delete' => true ));
;
}
时间表表单类型
<?php
namespace Nay\MMClinicsBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class TimetableType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('clinic')
->add('doctor')
->add('time','text',array('attr'=>array("data-role"=>"tagsinput")))
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Nay\MMClinicsBundle\Entity\Timetable'
));
}
/**
* @return string
*/
public function getName()
{
return 'nay_mmclinicsbundle_timetable';
}
}
答案 0 :(得分:2)
http://www.doctrine-project.org/jira/browse/DDC-3480
http://www.doctrine-project.org/jira/browse/DDC-3556
提到嵌入式广告只支持基本映射
因此,带有Embedded的ManyToOne仍未得到Doctrine 2的支持,很遗憾。
答案 1 :(得分:0)
即使我不确定这种推荐方式。但我已经按照以下方式解决了它。 首先从时间表表单类型中删除以下行:
->add('doctor')
在您的控制器中,createAction()会在您的医生实体保存/刷新后添加此代码。
$doctor = $form->getData();
if($doctor->getTimetables())
{
foreach ($doctor->getTimetables() as $timetable) {
$timetable->setDoctor($doctor);
$em->persist($timetable);
$em->flush();
}
}
在您的控制器updateAction()中,为表单handleRequest添加此代码。
$entity = $em->getRepository('YourBundle:Doctor')->find($id);
$originalTimetables = new ArrayCollection();
if($entity->getTimetables())
{
foreach ($entity->getTimetables() as $timetable) {
$originalTimetables->add($timetable);
}
}
在您的控制器中,updateAction()在表单handleRequest之后和医生实体刷新之前添加此代码。
$editForm->handleRequest($request);
if ($editForm->isValid()) {
foreach ($originalTimetables as $timetable)
{
if (false == $entity->getTimetables()->contains($timetable))
{
$timetable->getDoctor()->removeTimetable($timetable);
$em->remove($timetable);
$em->flush();
}
}
$em->flush();
在您的控制器中updateAction()在您的医生实体刷新后添加此代码。
$doctor = $editForm->getData();
if($doctor->getTimetables())
{
foreach ($doctor->getTimetables() as $timetable)
{
$timetable->setDoctor($doctor);
$em->flush();
}
}
}
我不确定,甚至没有尝试过$ em-&gt; flush()将在每个循环中使用,或者只有在它工作时才能解决循环的一面。 :)