Symfony 2表单bindRequest方法没有正确绑定(bind)一对多关系

标签 symfony one-to-many symfony-forms

我对 Symfony 2 框架相当陌生,因此由于对框架内部功能的理解不成熟而提出了一些新手问题。基本上,我有一个嵌入式表单,它是一对多的关系。我有一个名为 event 的实体,它至少有一个或多个时间对象

这是我的实体类

事件.php

<?php namespace KlikEvent\EventBundle\Entity; use Doctrine\ORM\Mapping as ORM;



> /**  
>      * @ORM\Entity  
>      * @ORM\Table(name="events")  
>      */ 
>     class Event {
> 
>     /**
>      * @ORM\Id
>      * @ORM\Column(type="integer")
>      * @ORM\GeneratedValue(strategy="AUTO")
>      */
>     protected $id;
> 
>     /**
>      * @ORM\Column(type="string", length=50)
>      */
>     protected $eventTitle;
> 
>     ....   
> 
>     /**
>     * @ORM\OneToMany(targetEntity="Time", mappedBy="event", cascade={"all"})
>     */
>     protected $eventTimes; 
> 
>     ......  
> 
>     public function __construct() {
>         $this->eventCategories = new \Doctrine\Common\Collections\ArrayCollection();
>         $this->eventTimes = new \Doctrine\Common\Collections\ArrayCollection();
>     }
> 
>     ...... setter + getter stuff ....
> 
> 
> 
>     /**
>      * Add eventTimes
>      *
>      * @param KlikEvent\EventBundle\Entity\Time $eventTimes
>      */
>     public function addTime(\KlikEvent\EventBundle\Entity\Time $eventTimes)
>     {
>         $this->eventTimes[] = $eventTimes;
>     }
> 
>     /**
>      * Get eventTimes
>      *
>      * @return Doctrine\Common\Collections\Collection 
>      */
>     public function getEventTimes()
>     {
>         return $this->eventTimes;
>     }
> 
>     ......
> 
>     }

时间.php

 <?php namespace KlikEvent\EventBundle\Entity;

 use Doctrine\ORM\Mapping as ORM;

 /**  * @ORM\Entity  * @ORM\Table(name="eventTime")  */ class Time {

     /**
      * @ORM\Id
      * @ORM\Column(type="integer")
      * @ORM\GeneratedValue(strategy="AUTO")
      */
     protected $id;

     /**
      * @ORM\ManyToOne(targetEntity="Event", inversedBy="eventTimes")
      * @ORM\JoinColumn(name="event_id", referencedColumnName="id")
      */
     protected $event;

     /**
      * @ORM\Column(type="datetime")
      */    
     protected $begin;

     /**
      * @ORM\Column(type="datetime")
      */    
     protected $end;


    ...... setter + getter stuff


     /**
      * Set event
      *
      * @param KlikEvent\EventBundle\Entity\Event $event
      */
     public function setEvent(\KlikEvent\EventBundle\Entity\Event $event)
     {
         $this->event = $event;
     }

     /**
      * Get event
      *
      * @return KlikEvent\EventBundle\Entity\Event 
      */
     public function getEvent()
     {
         return $this->event;
     }

  }

现在,当我制作嵌入表单时,我扩展了 AbstractType 以制作可重用的表单类 ( http://symfony.com/doc/current/book/forms.html#creating-form-classes )

这是我的表单类

时间类型.php

<?php

namespace KlikEvent\EventBundle\Form;

use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder;

class TimeType extends AbstractType {
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder
            ->add('begin')
            ->add('end')
        ;
    }

    public function getDefaultOptions ( array $options )
    {
        return array (
            'data_class'=>'KlikEvent\EventBundle\Entity\Time',
            );
    }

    public function getName()
    {
        return 'klikevent_eventbundle_timetype';
    } }

EventType.php

<?php

namespace KlikEvent\EventBundle\Form;

use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder;

use KlikEvent\EventBundle\Form\FeedbackType; use KlikEvent\EventBundle\Form\TimeType;

class EventType extends AbstractType {
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder
            ->add('feedback', new FeedbackType())
            ->add('eventTitle')
            ->add('eventLocation1')
            ->add('eventLocation2')
            ->add('eventShortDescription')
            ->add('eventDescription')
            ->add('eventFurtherDescription')
            ->add('eventCoverImage')
            ->add('eventImages')
            ->add('eventVideos')
            ->add('eventCategories')
            ->add('eventTimes', 'collection', 
                array ('type' => new TimeType(), 
                    'allow_add' => true,
                    'prototype' => true,
                    'by_reference' => false
                    ))


        ;
    }

    public function getName()
    {
        return 'klikevent_eventbundle_eventtype';
    } }

现在,每当我想在 Controller 中处理输入的输入时,我都会调用 $form->bindRequest($request) 方法,但它会抛出一个错误,表明事件类中没有 setEventTimes () 方法

Property "eventTimes" is not public in class "KlikEvent\EventBundle\Entity\Event". Maybe you should create the method "setEventTimes()"? 

这很奇怪,因为generate:doctrine:entities只生成addTimes方法而不是setEventTimes,我假设bindRequest方法的预期操作过程是将所有输入的时间对象添加到事件对象。我对这个错误感到困惑,很高兴获得帮助、指导,甚至提示我做错了什么

问候

编辑1..添加 Controller

Controller 在这里。我只显示相关的 Controller 方法,因为如果我显示所有内容就会太长

<?php

namespace KlikEvent\EventBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

use Doctrine\ORM\Query\ResultSetMapping;

use KlikEvent\EventBundle\Entity\Subscriber;
use KlikEvent\EventBundle\Entity\Event;
use KlikEvent\EventBundle\Entity\Category;
use KlikEvent\EventBundle\Entity\Feedback;
use KlikEvent\EventBundle\Entity\Time;

use KlikEvent\EventBundle\Form\SubscribeType;
use KlikEvent\EventBundle\Form\FeedbackType;
use KlikEvent\EventBundle\Form\EventType;
use KlikEvent\EventBundle\Form\TimeType;

class DefaultController extends Controller<?php

namespace KlikEvent\EventBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

use Doctrine\ORM\Query\ResultSetMapping;

use KlikEvent\EventBundle\Entity\Subscriber;
use KlikEvent\EventBundle\Entity\Event;
use KlikEvent\EventBundle\Entity\Category;
use KlikEvent\EventBundle\Entity\Feedback;
use KlikEvent\EventBundle\Entity\Time;

use KlikEvent\EventBundle\Form\SubscribeType;
use KlikEvent\EventBundle\Form\FeedbackType;
use KlikEvent\EventBundle\Form\EventType;
use KlikEvent\EventBundle\Form\TimeType;

class DefaultController extends Controller{

....


    public function defaultTipsEventOwnerAction( Request $request )
    {
        $feedback_event_owner = new Event();
        $time =  new Time(  );

        $feedback_event_owner->addTime( $time );

        $form_event_owner = $this->createForm(new EventType(), $feedback_event_owner);



        if ($request->getMethod() == 'POST') {


            $form_event_owner->bindRequest($request);

            if ($form_event_owner->isValid()) {

                $em = $this->getDoctrine()->getEntityManager();
                $em->persist($feedback_event_owner);
                $em->flush();

                $this->get('session')->setFlash('tips-notice-ok', 'Terima kasih untuk tips');

                $feedback_event_owner = new Feedback();
                $form_event_owner = $this->createForm(new FeedbackType(), $feedback_web);

                return $this->render .....

                );
            }
            else
            {
                $this->get('session')->setFlash('tips-notice-error', 'Maaf, Ada error. Coba lagi');
                 return $this->render .....
            }

        }
        return $this->render .....
    }

......


}

最佳答案

好的,经过几天的努力,我得到了这个。这是如此丑陋的黑客

基本上,generate:doctrine:entities 无法正确地为实体类生成适当的方法。这可能是也可能不是由于我的错误使用造成的,但在我的特定情况下,它没有正确创建 setEventTimes () 方法。

所以我所做的是,创建 setEventTimes () 方法,该方法基本上替换实体内的整个 eventTimes 集合

像这样

public function setEventTimes( $eventTimes )
{
    $this->eventTimes = $eventTimes;
}

这与Symfony生成脚本生成的方法不同,后者本质上是一一添加Time实体

/** THIS IS GENERATED
 * Add eventTimes
 *
 * @param KlikEvent\EventBundle\Entity\Time $eventTimes
 */
public function addTime(\KlikEvent\EventBundle\Entity\Time $eventTimes)
{
    $this->eventTimes[] = $eventTimes;
}

这解决了 Symfony 2 之前向我抛出的错误。

经进一步检查,时间实体没有对事件实体的引用,在数据库中,时间的event_id列始终输入为NULL。因此,为了避免这种情况,我添加了一些代码,在将对象持久保存到数据库之前,在每次输入对象时添加对事件实体的引用,如下面的代码片段

            foreach ( $feedback_event_owner->getEventTimes() as $times )
            {
                $times->setEvent($feedback_event_owner);
            }

希望这可以帮助任何像我一样面临同样问题的人。

感谢@flukey 为帮助我所做的努力:D

关于Symfony 2表单bindRequest方法没有正确绑定(bind)一对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10381411/

相关文章:

symfony - 如何在 Symfony2 中使用 FOSUserBundle 正确注销

Symfony2 语言环境检测 : not considering _locale in session

java - 具有一对多和多对多关系的 JOOQ pojos

java - Hibernate 在填充新持久的子集合时会复制父集合中的元素

javascript - symfony 4 - 如何清除 5 秒后的 Flash 消息?

php - 使用 EntityManagerDecorator 扩展 Doctrine EntityManager 在 UnitOfWork 中留下错误的引用

symfony - 修改消费者内部rabbitMQ发送的消息

java - hibernate "Provided id of the wrong type expected Long, got class DelayedPostInsertIdentifier"异常

php - Symfony4 Forms - 带有两个 choice_label 的 EntityType

symfony - 如何将 Symfony2 表单错误定位在正确的位置?