Symfony2具有属性对象持久性的多对多(多对一/一对多)

时间:2014-02-12 17:24:49

标签: symfony orm doctrine-orm many-to-many symfony-forms

我看了几个关于堆栈溢出的问题。许多问题似乎与我提出的问题很接近,但我无法在整个问题中找到答案。所以我在这里问一个全新的问题。

如果我省略了重要信息,请随时向我询问更多信息。

上下文

我正在构建一个Symfony2 Web应用程序,该应用程序管理日历上某些事件的某些用户可访问性。所以我有3个实体来代表它。 “Utilisateur”表示作为FOSUserBundle的扩展名的用户,“Evenement”表示事件和存储最后两者之间关系状态的中间对象。中间实体名称为“Disponibilite”,表示可用性。

我想做什么

当用户点击日历上的某个事件时,它会将他带到一个页面,在该页面中,他可以从下拉列表中指定他是否可用,然后撰写简短评论以激励他做出决定。然后,他提交了他的可用性,服务器保存了他的活动可用性。

问题

在我提交我的可用性的表格中,我似乎无法找到一种方法来注入有关对象的信息(Evenement和Utilisateur)。我不想创建实体选择字段,因为已经选择了用户和事件。我想制作一种隐藏的实体字段。那可能吗?这是好方法吗?

注意

用户可能在数据库中有或没有Disponibilite行。如果我们在事件E中查找用户A的可用性并且没有结果,则表示该用户从未提供此事件的可用性。在有结果的情况下,这意味着用户已经提供了他的可用性,并且正在修改他对该事件的可用性。

我从Symfony2开始,所以我可能会遗漏一些非常基本的东西

代码

以下是我的代码的简化。

实体\ Utilisateur.php

这是来自FOSUserBundle

的BaseUser的遗产
class Utilisateur extends BaseUser
{
    /**
     * @var integer
     * 
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
     protected $id;
}

实体\ Evenement.php

代表事件的实体。

class Evenement
{
    /**
     * @ORM\Id
     * @ORM\OneToMany(targetEntity="Musique\GestionBundle\Entity\Disponibilite", mappedBy="evenement")
     */
    private $disponibilite;

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
}

实体\ Disponibilite.php

表示Evenement与Utilisateur之间关系的实体。

class Disponibilite
{
    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="Musique\GestionBundle\Entity\Evenement",inversedBy="disponibilite")
     */
    private $evenement;

    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="Musique\UtilisateurBundle\Entity\Utilisateur")
     */
    private $utilisateur;
}

表单\ DisponibiliteType.php

我用来获取某个特定用户的可用性信息

class Disponibilite extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('disponibilite','choice', array(
                    'choices' => array("DispOui"=>"Disponible","DispCondition"=>"Incertain","DispNon"=>"Non-Disponible"),
                    'required' => true))
            ->add('raison')

            // Add entity field here? hidden field?
        ;
}

在控制器

加载DisponibiliteType(表单)视图的操作

function disponibiliteAction($id){
    $repo_evenement = $this->getDoctrine()->getManager()->getRepository('MusiqueGestionBundle:Evenement');
    $repo_dispo = $this->getDoctrine()->getManager()->getRepository('MusiqueGestionBundle:Disponibilite');

    $disponibilite = $repo_dispo->findBy(
            array('evenement'=>$id,'utilisateur'=>$this->getUser())
    );

    $evenement = $repo_evenement->find($id);

    if(count($disponibilite) > 0){
        $disponibilite = $disponibilite[0];
    } else {
        $disponibilite = new Disponibilite();
        $disponibilite->setEvenement($evenement);
        $disponibilite->setUtilisateur($this->getUser());
    }

    $form = $this->createForm(new DisponibiliteType(),$disponibilite);
    return $this->render('MusiqueGestionBundle:Calendrier:disponibilite.html.twig',array('form' => $form->createView(),'evenement'=> $evenement));
}

发布表单时触发的操作

function sendDisponibiliteAction(){
    $request = $this->getRequest();

    $repo_evenement = $this->getDoctrine()->getManager()->getRepository('MusiqueGestionBundle:Evenement');
    $evenement = $repo_evenement->find($request->get('evenement'));
    $repo_utilisateur = $this->getDoctrine()->getManager()->getRepository('MusiqueUtilisateurBundle:Utilisateur');
    $utilisateur = $repo_utilisateur->find($request->get('utilisateur'));

    $disponibilite = new Disponibilite();
    $disponibilite->setEvenement($evenement);
    $disponibilite->setUtilisateur($utilisateur);
    $form = $this->createForm(new DisponibiliteType(),$disponibilite);

    $form->bind($request);

    if($form->isValid()){
        $em = $this->getDoctrine()->getManager();
        $em->persist($disponibilite);
        $em->flush();
    }

    return $this->redirect($this->generateUrl("calendrier"));
}

1 个答案:

答案 0 :(得分:2)

实际上,这并不是那么难。我只用一个动作制作它,如果你愿意的话,你可以像以前一样分开它。

function disponibiliteAction($id)
{
    $em = $this->getDoctrine()->getManager();

    $repo_evenement = $em->getRepository('MusiqueGestionBundle:Evenement');
    $repo_dispo = $em->getRepository('MusiqueGestionBundle:Disponibilite');

    $evenement = $repo_evenement->findOneById($id);

    if (is_null($evenement)) {
        throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException();
    }

    $disponibilite = $repo_dispo->findOneBy(
        array('evenement'=>$evenement,'utilisateur'=>$this->getUser())
    );

    if (is_null($disponibilite)) {
        $disponibilite = new Disponibilite();
        $disponibilite->setEvenement($evenement);
        $disponibilite->setUtilisateur($this->getUser());
    }

    $form = $this->createForm(new DisponibiliteType(),$disponibilite);

    if ($this->getRequest()->isMethod('post')) {
        $form->submit($this->getRequest());

        if ($form->isValid()) {
            if ($disponibilite->getId() === null) {
                $em->persist($disponibilite);
            }
            $em->flush();

            return $this->redirect($this->generateUrl("calendrier"));
        }
    }

    return $this->render('MusiqueGestionBundle:Calendrier:disponibilite.html.twig',array('form' => $form->createView(),'evenement'=> $evenement));
}