所以我试图在Symfony 2中创建一个包含我的"Person"实体的注册表单。person实体有一个一对多连接,我希望注册表单允许用户选择连接的这个"多"侧的单个实例。
结构为Users
和Institutions
。一个用户可以拥有多个机构。我希望用户在注册时选择一个单一的机构(但模型允许以后更多)。
基本结构为:
RegistrationType -> PersonType -> PersonInstitutionType
…与对应的模型:
Registration (simple model) -> Person (doctrine entity) -> PersonInstitution (doctrine entity, oneToMany relation from Person)
我试图预填充一个空的Person
&PersonInstitution
记录在RegistrationController
中,但它给了我错误:
给定类型为"string or Symfony'Component'Form'FormTypeInterface", "TB' ctobbundle 'Entity'PersonInstitution"的期望参数
(上面的ok已被修复)。
我已经把代码从我的网站移到了下面,试图删除所有不相关的位。
src/结核/CtoBundle/形式/模型/Registration.php
namespace TB'CtoBundle'Form'Model;
use TB'CtoBundle'Entity'Person;
class Registration
{
/**
* @var Person
*/
private $person
private $termsAccepted;
}
src/结核/CtoBundle/形式/RegistrationType.php
namespace TB'CtoBundle'Form;
use TB'CtoBundle'Form'PersonType;
class RegistrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('person', new PersonType());
$builder->add('termsAccepted','checkbox');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TB'CtoBundle'Form'Model'Registration',
'cascade_validation' => true,
));
}
public function getName()
{
return 'registration';
}
}
src/结核/CtoBundle/实体/Person.php
namespace TB'CtoBundle'Entity;
use TB'CtoBundle'Entity'PersonInstitution
/**
* @ORM'Entity()
*/
class Person
{
/**
* @var ArrayCollection
* @ORM'OneToMany(targetEntity="PersonInstitution", mappedBy="person", cascade={"persist"})
*/
private $institutions;
}
src/结核/CtoBundle/形式/PersonType.php
namespace TB'CtoBundle'Form;
class PersonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('institutions', 'collection', array('type' => new PersonInstitutionType()))
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TB'CtoBundle'Entity'Person',
));
}
/**
* @return string
*/
public function getName()
{
return 'tb_ctobundle_person';
}
}
src/结核/CtoBundle/实体/PersonInstitution.php
namespace TB'CtoBundle'Entity
/**
* PersonInstitution
*
* @ORM'Table()
* @ORM'Entity
*/
class PersonInstitution
{
/**
* @ORM'ManyToOne(targetEntity="Person", inversedBy="institutions", cascade={"persist"})
*/
private $person;
/**
* @ORM'ManyToOne(targetEntity="Institution", inversedBy="members")
*/
private $institution;
/**
* @ORM'Column(type="boolean")
*/
private $approved;
}
src/结核/CtoBundle/形式/PersonInstititionType.php
namespace TB'CtoBundle'Form;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
class PersonInstitutionType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('approved')
->add('person')
->add('institution')
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TB'CtoBundle'Entity'PersonInstitution'
));
}
/**
* @return string
*/
public function getName()
{
return 'tb_ctobundle_personinstitution';
}
}
src/结核/CtoBundle/控制器/Registration.php
namespace TB'CtoBundle'Controller;
class RegisterController extends Controller
{
/**
*
* @param Request $request
* @return 'Symfony'Component'HttpFoundation'RedirectResponse|'Symfony'Component'HttpFoundation'Response
*/
public function registerAction(Request $request)
{
$registration = new Registration;
$person = new Person();
$institution = new PersonInstitution();
$person->addInstitution($institution);
$registration->setPerson($person);
// this causes error:
// Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
// $institution->setPerson($person);
$form = $this->createForm(new RegistrationType(), $registration);
$form->handleRequest($request);
if($form->isValid()) {
$registration = $form->getData();
$person = $registration->getPerson();
// new registration - account status is "pending"
$person->setAccountStatus("P");
// I'd like to get rid of this if possible
// for each "PersonInstitution" record, set the 'person' value
foreach($person->getInstitutions() as $rec) {
$rec->setPerson($person);
}
$em = $this->getDoctrine()->getManager();
$em->persist($person);
$em->flush();
}
return $this->render('TBCtoBundle:Register:register.html.twig', array('form' => $form->createView()));
}
}
下面是向Person实体和formType添加Collection字段的详细解决方案。您与注册实体的复杂问题可以解决与此。如果确实需要,我建议您使用这3个实体相关的连接。(只因为术语接受数据!?)
如果你不想改变你的观点,那么使用这个注释: 注册码:
use TB'CtoBundle'Entity'Person;
/**
* @ORM'OneToOne(targetEntity="Person")
* @var Person
*/
protected $person;
<<p> 人代码/strong>: use TB'CtoBundle'Entity'PersonInstitution;
/**
* @ORM'OneToMany(targetEntity="PersonInstitution", mappedBy = "person")
* @var ArrayCollection
*/
private $institutions;
/* I suggest you to define these functions:
setInstitutions(ArrayCollection $institutions),
getInstitutions()
addInstitution(PersonInstitution $institution)
removeInstitution(PersonInstitution $institution)
*/
<<p> PersonInstitution代码/strong>: use TB'CtoBundle'Entity'Person;
/**
* @ORM'ManyToOne(targetEntity="Person", inversedBy="institutions", cascade={"persist"}))
* @var Person
*/
private $person;
<<p> PersonType代码/strong>: use TB'CtoBundle'Form'PersonInstitutionType;
->add('institutions', 'collection', array(
'type' => new PersonInstitutionType(), // here is your mistake!
// Other options can be selected here.
//'allow_add' => TRUE,
//'allow_delete' => TRUE,
//'prototype' => TRUE,
//'by_reference' => FALSE,
));
<<p> PersonController代码/strong>: use TB'CtoBundle'Entity'Person;
use TB'CtoBundle'Entity'PersonInstitution;
/**
* ...
*/
public funtcion newAction()
{
$person = new Person;
$institution = new PersonInstitution;
$institution->setPerson($person);
$person->addInstitution($institution);
$form = $this->createForm(new PersonType($), $person); // you can use formFactory too.
// If institution field is required, then you have to check,
// that is there any institution able to chose in the form by the user.
// Might you can redirect to institution newAction in that case.
return array( '...' => $others, 'form' => $form);
}
如果你需要更多的帮助在小枝代码,然后问它