【问题标题】:symfony2 embedded form won't persist to databasesymfony2 嵌入式表单不会持久保存到数据库
【发布时间】:2015-09-29 19:12:39
【问题描述】:

我按照here 的文档进行了操作:但无法将示例持久保存到嵌入式表单的数据库中; Plant 类保存得很好。我假设控制器中的持久化和刷新方法处理两个实体的持久化。这是错误的假设吗?是否需要在flush前拦截并在控制器中手动设置?

无论如何,这是我的代码:

Plant Entity:

<?php

/**
 * @ORM\Entity(repositoryClass="Blogger\BlogBundle\Entity\Repository\PlantRepository")
 * @ORM\Table(name="plant")
 * @ORM\HasLifecycleCallbacks
 */
class Plant
{

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

   /**
    * @ORM\Column(type="array", nullable=true)
    * @ORM\ManyToMany(targetEntity="Blogger\BlogBundle\Entity\Picture", inversedBy="plants", cascade={"persist"})
    * @ORM\JoinTable(name="picture")
    */
    protected $pictures;

//...

    public function __construct()
    {
        $this->pictures = new ArrayCollection;
    }

//...

    /**
     * Add pictures
     *
     * @param \Blogger\BlogBundle\Entity\Picture $pictures
     * @return Plant
     */
    public function addPicture(\Blogger\BlogBundle\Entity\Picture $pictures)
    {
        $pictures->addPlant($this);
        $this->pictures[] = $pictures;
    }

    /**
     * Remove pictures
     *
     * @param \Blogger\BlogBundle\Entity\Picture $pictures
     */
    public function removePicture(\Blogger\BlogBundle\Entity\Picture $pictures)
    {
        $this->pictures->removeElement($pictures);
    }

    /**
     * Get pictures
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getPictures()
    {
        return $this->pictures;
    }
}   

图片实体:

<?php

namespace Blogger\BlogBundle\Entity;
use Doctrine\ORM\Mapping as ORM;


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

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

//...

    /**
     * @ORM\Column(type="text")
     */
    public $path;

    /**
     * @ORM\Column(type="array", nullable=true)
     * @ORM\ManyToMany(targetEntity="Blogger\BlogBundle\Entity\Plant", mappedBy="pictures")
     */
    private $plants;


    /**
     * Constructor
     */
    public function __construct()
    {
        $this->plants = new \Doctrine\Common\Collections\ArrayCollection();
    }

//...

    /**
     * Set path
     *
     * @param string $path
     * @return Picture
     */
    public function setPath($path)
    {
        $this->path = $path;

        return $this;
    }

    /**
     * Get path
     *
     * @return string 
     */
    public function getPath()
    {
        return $this->path;
    }

    /**
     * Add plants
     *
     * @param \Blogger\BlogBundle\Entity\Plant $plants
     * @return Picture
     */
    public function addPlant(\Blogger\BlogBundle\Entity\Plant $plants)
    {      
        if (!$this->plants->contains($plants)) {
            $this->plants->add($plants);
        }
    }

    /**
     * Remove plants
     *
     * @param \Blogger\BlogBundle\Entity\Plant $plants
     */
    public function removePlant(\Blogger\BlogBundle\Entity\Plant $plants)
    {
        $this->plants->removeElement($plants);
    }

    /**
     * Get plants
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getPlants()
    {
        return $this->plants;
    }
}

植物形态:

<?php 

namespace Blogger\BlogBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class PlantForm extends AbstractType
{

    public function __construct($em) {
        $this->em = $em;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {

//...

        $builder->add('pictures', 'collection', array(
            'type'      => new PictureForm(),
            'options'   => array(
                'data_class' => 'Blogger\BlogBundle\Entity\Picture'),
            'allow_add'    => true,
            'allow_delete' => true,
            'by_reference' => false,
        ));

    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Blogger\BlogBundle\Entity\Plant',
        ));
    }

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

图片形式:

<?php 

namespace Blogger\BlogBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class PictureForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

//...

        $builder->add('path', 'textarea'); 
//...

    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Blogger\BlogBundle\Entity\Picture',
        ));
    }

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

工厂控制器:

public function newAction(Request $request){   

$plant = new Plant();

$image1 = new Picture();
$plant->getPictures()->add($image1);

$form = $this->createForm(new PlantForm($this->getDoctrine()->getManager()), $plant);

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

    if ($form->isValid()) {
        $em = $this->getDoctrine()
               ->getEntityManager();
        $em->persist($plant);
        $em->flush();

        return $this->redirect($this->generateUrl('route', array(
            'id'    => $plant->getId()  
        )));
    }
}

return $this->render('Bundle:Plant:new.html.twig', array(
'form' => $form->createView()
));

}

我怀疑我没有正确映射数据库的注释。当我打开 phpadmin 时,数据库中没有定义任何关系。

【问题讨论】:

  • 在持久化植物之后添加这段代码并测试它:$em-&gt;persist($image1),也许它可以工作
  • 这确实有效,但我忽略了取出 $image1 虚拟数据(一开始就不应该存在)。我已经这样做了,当图片被动态添加到表单时,它现在不会保留图片。植物中的图片字段实际上是在持久化整个植物对象......包括动态添加的图片。这是有道理的。它被映射为一个数组。这些字段应该映射为什么?将它们留空会导致错误。

标签: symfony doctrine-orm


【解决方案1】:

我想通了。我的注释确实是一个错误。这个问题实际上在here 的帖子中得到了回答。对于我的解决方案,它看起来像这样:

植物实体:

class Plant
{

//..   

   /**
    * @ORM\ManyToMany(targetEntity="Blogger\BlogBundle\Entity\Picture", inversedBy="plants", cascade={"persist"})
    * @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
    */
    protected $pictures;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->pictures = new ArrayCollection();
    }   

    public function addPicture(\Blogger\BlogBundle\Entity\Picture $pictures)
    {
        $pictures->addPlant($this);
        $this->pictures[] = $pictures;
    }   

//..

}

class Picture
{

//..

    /**
     * @ORM\ManyToMany(targetEntity="Blogger\BlogBundle\Entity\Plant", mappedBy="pictures", cascade={"persist", "remove"})
     */
    private $plants;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->plants = new \Doctrine\Common\Collections\ArrayCollection();
    }

    public function addPlant(\Blogger\BlogBundle\Entity\Plant $plants)
    {
        if (!$this->plants->contains($plants)) {
            $this->plants->add($plants);
        }
    }   

//..    

}

控制器:

公共函数newAction(请求$request){

$plant = new Plant();

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

    if ($form->isValid()) {
        $em = $this->getDoctrine()
               ->getEntityManager();
        $em->persist($plant);
        $em->flush();
        return $this->redirect($this->generateUrl('BloggerBlogBundle_plant_library_show', array(
            'id'    => $plant->getId()  
        )));
    }
}

return $this->render('BloggerBlogBundle:Library:new.html.twig', array(
'form' => $form->createView()
));

}

也许对其他人有用:此映射创建了一个名为 plant_picture 的新表,其中包含关联。我很惊讶地发现“图片”列根本没有添加到 Plant 实体中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 1970-01-01
    • 2014-02-26
    相关资源
    最近更新 更多