繁体   English   中英

Symfony2注册表单,仅包含收集字段的单个记录

[英]Symfony2 Registration form with only single record of collection field

因此,我试图在Symfony 2中创建一个包含我的“ Person”实体的注册表单。 人员实体具有一对多联接,我希望注册表单允许用户选择联接的此“许多”面的单个实例。

结构是UsersInstitutions 用户可以拥有许多机构。 我希望用户在注册时选择一个机构(但是该模型允许稍后再使用)。

基本结构是:

RegistrationType-> PersonType-> PersonInstitutionType

…对应型号:

注册(简单模型)->人员(学说实体)->人员机构(学说实体,来自Person的oneToMany关系)

我试图在RegistrationController预填充一个空的PersonPersonInstitution记录,但它给了我错误:

给定类型为“字符串或Symfony \\ Component \\ Form \\ FormTypeInterface”,“ TB \\ CtoBundle \\ Entity \\ PersonInstitution”的参数

(确定已被修复)。

我已将代码从我的网站移至下面的位置,试图删除所有不相关的位。

SRC / TB / CtoBundle /表格/型号/和registration.php

namespace TB\CtoBundle\Form\Model;
use TB\CtoBundle\Entity\Person;
class Registration 
{
  /**
   * @var Person
   */
  private $person
  private $termsAccepted;
}

SRC / TB / 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 / TB / 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 / TB / 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 / TB / 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 / TB / 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 / TB / 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()));
    }
}

这是将Collection字段添加到Person实体和formType的详细解决方案。 您可以通过注册实体解决与注册实体相关的复杂问题。 如果确实需要,我建议您使用与这3个实体相关的连接。 (仅由于条款已接受数据!?)

如果您不会改变意见,请使用以下注释: 注册代码

use TB\CtoBundle\Entity\Person;
/**
  * @ORM\OneToOne(targetEntity="Person")
  * @var Person
  */
protected $person;

人员代码

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)
*/

机构代码

use TB\CtoBundle\Entity\Person;

/**
  * @ORM\ManyToOne(targetEntity="Person", inversedBy="institutions", cascade={"persist"}))
  * @var Person
  */
private $person;

PersonType代码

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,
));

PersonController代码

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);
}

如果您需要细枝代码方面的更多帮助,请寻求帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM