Symfony形式的多个相关一对多关系
我正试图让多重关系(多重、依赖的一对多关系)形式发挥作用,但没有成功。我用的是symfony2.3和FOSUserbundle 实体用户Symfony形式的多个相关一对多关系,symfony,symfony-forms,symfony-2.3,Symfony,Symfony Forms,Symfony 2.3,我正试图让多重关系(多重、依赖的一对多关系)形式发挥作用,但没有成功。我用的是symfony2.3和FOSUserbundle 实体用户 use FOS\UserBundle\Entity\User as BaseUser; [...] /** * @ORM\Entity * @Gedmo\Loggable * @ORM\Table(name="ta_user", indexes={@ORM\Index(name="IDX_LOGIN_TO
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;
用户管理器
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;
}
实体用户生活方式
/**
* @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;
然后,有一个表单类型
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,
))
现在应该有一个相关的注册生活方式类型
。但我不知道它应该是什么样子。我希望在我的注册表中有三个选择字段,显示一个问题(作为标签)和一堆与这些问题相关的答案(作为选择字段)。UserManager会为新创建的用户分配三个问题,以便用户可以通过以下方式获得问题:
$lifestyles = $user->getLifestyles();
foreach ($lifestyles as $lifestyle) {
$question = $lifestyle->getQuestion(); // echo $question->getQuestion();
$answers = $lifestyle->getQuestion()->getAnswers(); // loop through $answers and echo $answer->getAnswer();
}
但是我如何修改表单类型以使其正常工作。重要提示:我的目的是尽可能多地使用内置功能,并通过注入服务容器和实体管理器来避免表单类型和其他类型的膨胀。找到了一个解决方案,也许有人可以使用它。问题似乎是,
LifestyleQuestion
和LifestyleAnswer
在同一个对象上是1:n关系(userlifetyle
),因此Symfony不知道如何处理它,即使我已经在UserManager
中将LifestyleQuestion
设置为特定问题。关于必须使用表单侦听器,因此父对象在子表单中可用。下面是我的“简单”注册生活方式类型(不使用任何注入容器或管理器):
找到了一个解决方案,也许有人可以使用它。问题似乎是,
LifestyleQuestion
和LifestyleAnswer
在同一个对象上是1:n关系(userlifetyle
),因此Symfony不知道如何处理它,即使我已经在UserManager
中将LifestyleQuestion
设置为特定问题。关于必须使用表单侦听器,因此父对象在子表单中可用。下面是我的“简单”注册生活方式类型(不使用任何注入容器或管理器):
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,
));
}
}