我有两个实体:Doctor&时间表其中一个医生有多个时间表(OneToMany),多个时间表有一个医生(ManyToOne)。我想从医生创建表单屏幕创建许多时间表。所以,我跟随文章嵌入表单集合一切都很好,只是我在时间表创建会话上看到医生下拉列表,这意味着我只能为现有医生创建时间表我知道医生下拉列表来自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(),
);
}
我读过所有类似的问题,但没有解决方案。请任何人帮我举一些符号初学者能理解的例子。非常感谢。
下面是表格结构&相关代码:
医生实体表
id nbsp nbsp;INT PRIMARY KEY AUTO_INCREMENT
name VARCHAR(55)不为空
时间表实体表
id nbsp nbsp nbsp nbsp INT主键AUTO_INCREMENT
doctor_id nbsp;INT(医生的外键)
clinic_id nbsp INT(诊所的外键)
_time nbsp nbsp VARCHAR(255)NOT NULL
医生实体类
<?php
namespace NayMMClinicsBundleEntity;
use DoctrineORMMapping as ORM;
use DoctrineCommonCollectionsArrayCollection;
use SymfonyComponentHttpFoundationFileUploadedFile;
use SymfonyComponentValidatorConstraints as Assert;
/**
* Doctor
*
* @ORMTable(name="doctors")
* @ORMEntity(repositoryClass="NayMMClinicsBundleEntityDoctorRepository")
*/
class Doctor
{
/**
* @var ArrayCollection
*
* @ORMOneToMany(targetEntity="Timetable", mappedBy="doctor", cascade={"persist"})
*/
public $timetables;
/**
* @var integer
*
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORMColumn(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 NayMMClinicsBundleEntity;
use DoctrineORMMapping as ORM;
use DoctrineCommonCollectionsArrayCollection;
/**
* Timetable
*
* @ORMTable(name="timetables")
* @ORMEntity(repositoryClass="NayMMClinicsBundleEntityTimetableRepository")
*/
class Timetable
{
/**
* @var Clinic
*
* @ORMManyToOne(targetEntity="Clinic", inversedBy="timetables")
* @ORMJoinColumn(name="clinic_id", referencedColumnName="id")
*/
public $clinic;
/**
* @var Doctor
*
* @ORMManyToOne(targetEntity="Doctor", inversedBy="timetables")
* @ORMJoinColumn(name="doctor_id", referencedColumnName="id")
*/
public $doctor;
/**
* @var integer
*
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var integer
*
* @ORMColumn(name="clinic_id", type="integer")
*/
private $clinicId;
/**
* @var integer
*
* @ORMColumn(name="doctor_id", type="integer")
*/
private $doctorId;
/**
* @var string
*
* @ORMColumn(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 NayMMClinicsBundleForm;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolverInterface;
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' => 'NayMMClinicsBundleEntityTimetable'
));
}
/**
* @return string
*/
public function getName()
{
return 'nay_mmclinicsbundle_timetable';
}
}
http://www.doctrine-project.org/jira/browse/DDC-3480
http://www.doctrine-project.org/jira/browse/DDC-3556
提到嵌入式只支持基本映射
因此,带有嵌入式的ManyToOne仍然不受条令2的支持,这很遗憾。
即使我也不确定这种方式是否推荐。但我用以下方法解决了这个问题。首先从时间表表格类型中删除以下行:
->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->flush()在每个循环中都需要,或者只在循环的一侧工作一次。:)