1

I'm trying to get a multi-relation (multiple, dependent one-to-many relations) form working, but no success. I'm using Symfony 2.3 with FOSUserbundle.

Entity User

    use FOS\UserBundle\Entity\User as BaseUser;
    [...]

    /**
     * @ORM\Entity
     * @Gedmo\Loggable
     * @ORM\Table(name="ta_user", indexes={@ORM\Index(name="IDX_LOGIN_TOKEN", columns={"login_token"})})
     */
    class User extends BaseUser
    {
            [...]

        /**
         * @ORM\OneToMany(targetEntity="UserLifestyle", mappedBy="user", fetch="LAZY", cascade={"persist", "remove"})
         */
        protected $lifestyle;

UserManager

    use Doctrine\ORM\EntityManager;
    use FOS\UserBundle\Entity\UserManager as BaseUserManager;
    use Acme\UserBundle\Entity\LifestyleQuestion;
    use Acme\UserBundle\Entity\UserLifestyle;
    [...]

    class UserManager extends BaseUserManager {
        public function createUser() {
            $user = parent::createUser();
            $lifestyle = new UserLifestyle();
            $lifestyle->setQuestion($this->objectManager->getReference('Acme\UserBundle\Entity\LifestyleQuestion', 1));
            $user->addLifeStyle($lifestyle);
            $lifestyle = new UserLifestyle();
            $lifestyle->setQuestion($this->objectManager->getReference('Acme\UserBundle\Entity\LifestyleQuestion', 2));
            $user->addLifeStyle($lifestyle);
            $lifestyle = new UserLifestyle();
            $lifestyle->setQuestion($this->objectManager->getReference('Acme\UserBundle\Entity\LifestyleQuestion', 3));
            $user->addLifeStyle($lifestyle);
            return $user;
        }

Entity UserLifestyle

    /**
     * @ORM\Entity
     * @Gedmo\Loggable
     * @ORM\Table(name="ta_user_lifestyle")
     */
    class UserLifestyle
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="smallint")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;

        /**
         * @ORM\ManyToOne(targetEntity="User", inversedBy="lifestyle")
         * @ORM\JoinColumn(name="user_id")
         */
        protected $user;

        /**
         * @ORM\ManyToOne(targetEntity="LifestyleQuestion", inversedBy="answeredByUser")
         * @ORM\JoinColumn(name="question_id")
         */
        protected $question;

        /**
         * @ORM\ManyToOne(targetEntity="LifestyleAnswer", inversedBy="userAnswers")
         * @ORM\JoinColumn(name="answer_id")
         * @Gedmo\Versioned
         */
        protected $answer;

Then, there's a form type

    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolverInterface;
    use Doctrine\ORM\EntityRepository;

    class RegistrationType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('email', NULL, array('label' => 'E-Mail'))
                            [...]
                ->add('lifestyle', 'collection', array(
                    'type' => new RegistrationLifestyleType(),
                    'allow_add' => false,
                    'allow_delete' => false,
                    'label' => false,
                ))

and now there should be a related RegistrationLifestyleType. But I've no idea how it should look like. I expect, that there are three choice fields in my registration form, showing a question (as label) and bunch of answers (as choice field) related to these questions. The UserManager assigns three questions to a newly created user, so one can get a question with:

    $lifestyles = $user->getLifestyles();
    foreach ($lifestyles as $lifestyle) {
        $question = $lifestyle->getQuestion(); // echo $question->getQuestion();
        $answers = $lifestyle->getQuestion()->getAnswers(); // loop through $answers and echo $answer->getAnswer();
    }

But how I can modify the form type, to get this working. Important: my intention is to use built-in functionality as most as possible and trying to avoid inflating form types and others by injecting service containers and entity managers.

4

1 回答 1

1

找到了解决方案,也许有人可以使用它。问题似乎是 1:n 关系在同一个对象 ( LifestyleQuestion)上,所以 Symfony 不知道如何处理它,即使我已经将 设置为特定问题。关于https://stackoverflow.com/a/9729888/672452必须使用表单侦听器,因此父对象以子表单可用。所以这是我的“简单” (不使用任何注入的容器或管理器):LifestyleAnswerUserLifestyleLifestyleQuestionUserManagerRegistrationLifestyleType

use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Security\Core\SecurityContext;

class RegistrationLifestyleType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($builder) {
            $form = $event->getForm();
            $lifestyle = $event->getData();
            if (!($lifestyle instanceof \Acme\UserBundle\Entity\UserLifestyle) || !$lifestyle->getQuestion()) return;
            $label = $lifestyle->getQuestion()->getQuestion();
            $questionId = $lifestyle->getQuestion()->getId();
            $form->add('answer', 'entity', array(
                'class' => 'AcmeUserBundle:LifestyleAnswer',
                'empty_value' => '',
                'property' => 'answer',
                'query_builder' => function(EntityRepository $er) use ($questionId) {
                    return $er
                        ->createQueryBuilder('t1')
                        ->andWhere('t1.question = :question')
                        ->setParameter('question', $questionId)
                        ->orderBy('t1.answer', 'ASC')
                    ;
                },
                'label' => $label,
            ));
        });
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\UserBundle\Entity\UserLifestyle',
            'error_bubbling' => false,
        ));
    }
}
于 2013-09-11T09:32:29.080 回答