Symfony:嵌入ManyToOne-OneToMany关系的表单集合

时间:2014-04-23 09:40:14

标签: forms symfony orm doctrine-orm

我正在运行带有Doctrine和这三个(相关)实体的Symfony 2.3:发布作者 AuthorPublication 作者发布都与 AuthorPublication 有多对一的关系(因此它基本上是<...之间的多对多关系) strong>作者和发布但我需要 AuthorPublication 实体来订购出版物的作者)

我希望有一个表单,用户可以在其中创建新的出版物,并根据需要为该出版物选择尽可能多的作者。

我研究了这篇文章:How to Embed a Collection of Forms但我不明白如何将其应用于我的问题,因为 AuthorPublication 实体介于两者之间。

相关守则:

公开

<?php

namespace ind\PubBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="ind\PubBundle\Repository\PublicationRepository")
 * @ORM\Table("publications")
 */
class Publication {

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

    /**
     * @ORM\OneToMany(targetEntity="AuthorPublication", mappedBy="publication")
     * @ORM\OrderBy({"order_id" = "ASC"})
     */
    protected $publicationAuthors;


//some more attributes + getters/seters
?>

作者

<?php

namespace ind\PubBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table("aid_author")
 */
class Author {

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

    /**
     * @ORM\Column(type="string", length=255)
     */
    protected $author_surname;

    /**
     * @ORM\Column(type="string", length=255)
     */
    protected $author_forename;

    /**
     * @ORM\OneToMany(targetEntity="AuthorPublication", mappedBy="author")
     */
    protected $authorPublication;
?>

AuthorPublication

<?php

namespace ind\PubBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table("aid_pid")
 */
class AuthorPublication {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     */
    protected $aid;

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     */
    protected $pid;

    /**
     * @ORM\Column(type="integer")
     */
    protected $order_id;

    /**
     * @ORM\ManyToOne(targetEntity="Publication", inversedBy="publicationAuthors")
     * @ORM\JoinColumn(name="pid", referencedColumnName="pid")
     */
    protected $publication;

    /**
     * @ORM\ManyToOne(targetEntity="Author", inversedBy="authorPublication")
     * @ORM\JoinColumn(name="aid", referencedColumnName="aid")
     */
    protected $author;
?>

1 个答案:

答案 0 :(得分:3)

  1. 您必须制作AuthorPublicationType表单。您将字段作者设为'entity',将其他字段设为...

  2. 您制作出版物类型包括AuthorPublication(Embedded Forms)。

  3. 然后您可以使用prototype和非常简单的javascript添加新的AuthorPublication。

  4. 请注意,当您必须首先使用authorPublication attribut保存您的实体出版物时。在更新发布之后,例如使用Publication和LifecycleCallbacks中的临时ArrayCollection定义authorPublication。

  5. 编辑:示例。

    我的实体是Sport OneToMany SportParam ManyToOne ConfigParam。 SportParam由Sport,ConfigParam和值组成。

    我想用多个ConfigParam创建一个新的Sport:

    1. SportParamType:

      public function buildForm(FormBuilderInterface $builder, array $options)
      {
          $builder        
              ->add('ConfigParam', 'entity', array(
                  'class'    => 'PPHBSportScoringBundle:ConfigParam',
                  'property' => 'nom',
                  'multiple' => false,
                  'label'=>'Paramètre'
              ))
              ->add('valeur','number',array('precision'=>2))
          ;
      }
      
    2. SportType

      public function buildForm(FormBuilderInterface $builder, array $options)
      {
          $builder
              ->add('nom')
              ->add('SportParams',  'collection', array(
                  'type'=> new SportParamType(),
                  'allow_add'    => true,
                  'allow_delete' => true,
                  'by_reference'=> false
              ))
          ;
      
      }
      
    3. 我的form.html.twig:

      {{ form_start(form) }}
        {{ form_errors(form) }} 
        {{ form_row(form.nom) }}
        <ul class=SportParams data-prototype="{{ form_widget(form.SportParams.vars.prototype)|e }}">
          {% for param in form.SportParams %}
            <li>
            {{ form_errors(param.ConfigParam) }}
            {{ form_widget(param.ConfigParam) }}
            {{ form_errors(param.valeur) }}
            {{ form_widget(param.valeur) }}
            </li>
          {% endfor %}
        </ul>
        <input type="submit" class="btn btn-primary" />
      {{ form_end(form) }}
      

      我的Javascript精炼,因为它包含更多代码(AJAX调用)。它可能包含一些错误。如果不清楚,请查看documentation

      <script type="text/javascript">
      
      var $container = $('ul.SportParams');
      // button to add a new SportParam
      var $addSportParamLink = $('<a href="#" id="ajout_param" class="btn btn-primary btn-xs">Ajouter un paramètre</a>');  
      var $newLinkLi = $('<li></li>').append($addSportParamLink);
      
      $(document).ready(function() {
          //delete button on each existing SportParam
          $container.find('li').each(function() {
              addParamFormDeleteLink($(this));
          });       
      
          //add button
          $container.append($newLinkLi);
      
          // adding a new form when cliking Add button
          $addSportParamLink.on('click',function(e) {         
              e.preventDefault(); // évite qu'un #apparaisse dans l'URL
              var index = $container.children().length-1;
      
              addParamForm($container,$newLinkLi);
      
              var bAffiche; 
      
              return false;
          });
      
          // adding a new form SportParam
          function addParamForm($container, $newLinkLi) {
      
              var $prototype = $container.attr('data-prototype');
      
              var newForm = $prototype.replace(/__name__/g, $container.children().length-1);  
      
              var $newFormLi = $('<li></li>').append(newForm);
              $newLinkLi.before($newFormLi);
      
              addParamFormDeleteLink($newFormLi);
          }
      
          function addParamFormDeleteLink($paramFormLi){
              var $removeFormA = $('<a href="#" class="btn btn-danger  btn-xs">Supprimer</a>');   
              $paramFormLi.append($removeFormA);
              $removeFormA.on('click', function(e) {
                  e.preventDefault();
                  $paramFormLi.remove();
              });
          }
      
      });
      </script>
      
    4. 体育实体致电回复:

      /**
       * sport
       *
       * @ORM\Table()
       * @ORM\Entity
       * @ORM\HasLifecycleCallbacks
       * @ORM\Entity(repositoryClass="SportRepository")
       */
      class Sport
      {
      
      ...Entity attribut...
      
          /**
           * @var ArrayCollection
           *
           * To save Sport without SportParams
           */
          private $SportParamsTMP;
      
      ...getter and setter ...
      
          /**
           * @ORM\PrePersist
           */
          public function saveSportParams()
          {   
            $this->SportParamsTMP = $this->SportParams;
            $this->SportParams = null;
          }
          /**
           * @ORM\PostPersist
          */
          public function restoreSportParams()
          {
            if ($this->SportParamsTMP == !null) {
              $this->SportParams = $this->SportParamsTMP;
            }
            $this->SportParamsTMP = null;
          }
      
      }   
      

      最后控制器的功能是添加一个新的Sport:

      public function addAction()
      {
        $sport = new Sport();
        $form = $this->createForm(new SportType(), $sport);
      
        $request = $this->getRequest();
      
        if ($request->getMethod() == "POST") {
          $form->bind($request);
          if($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
      
            $em->persist($sport);
            //saving sport without parameter
            $em->flush();
      
            //updating sport with parameter
            $em->flush();
      
            return $this->redirect($this->generateUrl('pphb_sport_liste'));
          }
        }
      
        return $this->render('PPHBSportScoringBundle:Championnat/Sport:add.html.twig', array(
                   'form' => $form->createView(),
        ));
      }
      
    5. 我希望它有所帮助 不知道这是否是最好的方法,但它对我有用。如果要改进的地方请告诉我。