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

Symfony2具有属性对象持久性的多对多(多对一/一对多),symfony,orm,doctrine-orm,many-to-many,symfony-forms,Symfony,Orm,Doctrine Orm,Many To Many,Symfony Forms,我看了几个关于堆栈溢出的问题。许多问题似乎与我所问的很接近,但我无法从中找到答案。所以这里我要问一个全新的问题 如果我遗漏了一些重要的事情,请随时询问我更多的信息 上下文 我正在构建一个Symfony2 Web应用程序,用于管理某些用户对日历上某些事件的访问。所以我有3个实体来表示它。“Usilizateur”是指作为FOSUserBundle扩展的用户,“evennement”是指事件和存储最后两个事件之间关系状态的中间对象。中间实体名称为“Disponibilite”,表示可用性 我想做什么

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

如果我遗漏了一些重要的事情,请随时询问我更多的信息

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

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

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

注 用户在数据库中可能有也可能没有Disponibilite行。如果我们寻找用户A对事件E的可用性,但没有结果,这意味着该用户从未给出过该事件的可用性。如果有结果,则表示用户已经给出了可用性,并且当前正在修改事件的可用性

我从Symfony2开始,所以我可能缺少一些非常基本的东西

代码 这是我的代码的简化

Entity\usilizateur.php 这是FOSUserBundle的BaseUser的传统

class Utilisateur extends BaseUser
{
    /**
     * @var integer
     * 
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
     protected $id;
}
Entity\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;
}
Entity\Disponibilite.php 一个代表晚上和利用者之间关系的实体

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;
}
Form\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 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"));
}

事实上,这并不难。我只用一个动作就成功了,如果你愿意,你可以像以前一样分割它

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

当我执行$disponibilite->setEvenement($evenement)时,实体信息是否从表单传递到POST中?只有身份证?这正是让我困惑的地方。对不起,我不明白你的问题。你能换一种说法吗?我想我的问题是,当我收到POST请求时绑定(或者->你的例子中的sumbit)到$disponibilite,它实际上并没有绑定链接的实体。例如:加载表单时,我将$evenement和$this->getUser()附加到$disponibilite实体,然后将其传递给表单生成器。到现在为止,一直都还不错。提交表单时,我希望绑定时,绑定将绑定链接实体对象,因为它是在表单中传递的。但是打印$disponibilite->getEnsemble时,会显示NULL。我可以得到$disponibilite->getRaison(),这是注释文本。您确定
getevennement()
在绑定之前不为空吗?表单提交不应替换
evement
属性,因为它不在表单类型中。另外,我将从数据库中获取$disponibilite,并尝试测试它。它应该是
'evement'=>$evement
而不是
'evement'=>$id
。您可以通过在
DisponibiliteType
中添加隐藏字段
user
event
使它们可用,但您不需要也不推荐这样做。通常通过实体设置器或通过
$form->setData()
设置它们。一切都好。但是,当您将用户和事件字段添加到表单中时,用户可以手动更改它们我很确定您不希望发生这种情况,是吗?:)
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));
}