Symfony关系OneToMany

时间:2017-01-12 09:08:26

标签: symfony collections relation

我遇到了这个问题。我尝试为一个带有集合的实体上传一张或多张图片但是当我提交表单时我发现了这个错误:

Symfony\Component\Validator\ConstraintViolation
Object(Symfony\Component\Form\Form).data.imagearticle[0].Article = null

这是因为在我的实体ImageArticle中我把它放了:

namespace AD\PlatformBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
use AD\PlatformBundle\Entity\Article;

/**
 * ImageArticle
 *
 * @ORM\Table()
 * @ORM\Entity()
 * @ORM\HasLifecycleCallbacks
 */
class ImageArticle
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="url", type="string", length=255)
     */
    private $url;

    /**
     * @var string
     *
     * @ORM\Column(name="alt", type="string", length=255)
     */
    private $alt;

    /**
     * @var File
     *  
     * @Assert\File(
     *     maxSize = "1M",
     *     mimeTypes = {
     *          "image/jpeg", 
     *          "image/gif", 
     *          "image/png", 
     *          },
     *     maxSizeMessage = "La taille maximum du fichier doit etre inférieur ou égale à 1MB. Pour reduire sa taille vous pouvez utiliser le site : compressjpeg.com",
     *     mimeTypesMessage = "Seulement les fichiers .jpeg / .gif /.png sont acceptés"
     * )
     */
    private $file;

    private $tempFileName;


    /**
     * @var Article
     * @ORM\ManyToOne(targetEntity="AD\PlatformBundle\Entity\Article", inversedBy="imagearticle")
     * @ORM\JoinColumn(nullable=false)
     * @Assert\NotNull()
     */
    private $Article;



    public function getFile()
    {
        return $this->file;
    }

    public function setFile(UploadedFile $file)
    {

        $this->file = $file;

        if (null !== $this->url)
        {
            $this->tempFileName = $this->url;
            $this->url=null;
            $this->alt=null;
        }
    }
    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set url
     *
     * @param string $url
     *
     * @return ImageArticle
     */
    public function setUrl($url)
    {
        $this->url = $url;

        return $this;
    }

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

    /**
     * Set alt
     *
     * @param string $alt
     *
     * @return ImageArticle
     */
    public function setAlt($alt)
    {
        $this->alt = $alt;

        return $this;
    }

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

    /**
     * @ORM\PrePersist()
     * @ORM\PreUpdate()
     */
    public function preUpload()
    {
        if (null === $this->file)
        {
            return;
        }


        //On add un extension pour le fichier.
        $this->url = $this->file->guessExtension();
        //Le alt est le nom du fichier du client.
        $this->alt=  $this->file->getClientOriginalName();

    }

    /**
     * 
     * @ORM\PostPersist()
     * @ORM\PostUpdate()
     * 
     */
    public function upload()
    {
        if(null=== $this->file)
        {
            return;
        }

        //Si ancien fichier on supprime
        if(null !== $this->tempFileName)
        {
            $oldFile = $this->getUploadRootDir().'/'.$this->id.'.'.$this->tempFileName;
            if (file_exists($oldFile))
            {
                unlink($oldFile);
            }
        }

        //On deplace
        $this->file->move
        (
            $this->getUploadRootDir(),
            $this->id.'.'.$this->url    
        );
//        chmod($this->getUploadRootDir().'/'.$this->id.'.'.$this->url,644);
    }

    /**
     *@ORM\PreRemove()
     */
    public function preRemoveUpload()
    {
        $this->tempFileName = $this->getUploadRootDir().'/'.$this->id.'.'.$this->url;
    }

    /**
     * 
     * @ORM\PostRemove()
     */
    public function removeUpload()
    {
        if(file_exists($this->tempFileName))
        {
            unlink($this->tempFileName);
        }
    }
    public function getUploadDir()
    {
        return 'upload/img/blog/';
    }

    protected function getUploadRootDir()
    {
        return __DIR__.'/../../../../web/'.$this->getUploadDir();
    }

    public function __toString()
    {
        return $this->getUploadDir().$this->id.'.'.$this->getUrl();
    }

    /**
     * Set source
     *
     * @param string $source
     *
     * @return Image
     */

    /**
     * Set article
     *
     * @param \AD\PlatformBundle\Entity\Article $article
     *
     * @return ImageArticle
     */
    public function setArticle(\AD\PlatformBundle\Entity\Article $article = null)
    {

        $this->article = $article;

        return $this;
    }

    /**
     * Get article
     *
     * @return \AD\PlatformBundle\Entity\Article
     */
    public function getArticle()
    {
        dump($this->article);
        return $this->article;
    }

但当我删除此Assert \ NotNull时,我的错误是"列article_id不能为空"

这是我的文章实体:

  <?php

namespace AD\PlatformBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Validator\Constraints as Assert;


/**
 * Article
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class Article
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="titre1", type="string", length=255)
     */
    private $titre1;

    /**
     * @var string
     *
     * @ORM\Column(name="titre2", type="string", length=255)
     */
    private $titre2;

    /**
     * @var string
     *
     * @ORM\Column(name="description", type="text")
     */
    private $description;

    /**
     * @ORM\ManyToMany(targetEntity="AD\UserBundle\Entity\User")
     * @ORM\JoinColumn(nullable=false)
     */
    private $user;

    /**
     *
     * @ORM\OneToMany(targetEntity="AD\PlatformBundle\Entity\ImageArticle", mappedBy="article", cascade="all", orphanRemoval=true)
     * @Assert\Valid()
     * @ORM\OrderBy({"position" = "ASC"})
     *
     */


    private $imagearticle;

    /**
     * @Gedmo\Slug(fields={"titre1"})
     * @ORM\Column(length=128, unique=true)
     */
    private $slugurl;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set titre1
     *
     * @param string $titre1
     *
     * @return Article
     */
    public function setTitre1($titre1)
    {
        $this->titre1 = $titre1;

        return $this;
    }

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

    /**
     * Set titre2
     *
     * @param string $titre2
     *
     * @return Article
     */
    public function setTitre2($titre2)
    {
        $this->titre2 = $titre2;

        return $this;
    }

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

    /**
     * Set description
     *
     * @param string $description
     *
     * @return Article
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

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

    /**
     * Set user
     *
     * @param \AD\UserBundle\Entity\User $user
     *
     * @return Article
     */
    public function setUser(\AD\UserBundle\Entity\User $user)
    {
        $this->user = $user;

        return $this;
    }

    /**
     * Get user
     *
     * @return \AD\UserBundle\Entity\User
     */
    public function getUser()
    {
        return $this->user;
    }

    /**
     * Set imagearticle
     *
     * @param \AD\PlatformBundle\Entity\ImageArticle $imagearticle
     *
     * @return Article
     */
    public function setImagearticle(\AD\PlatformBundle\Entity\ImageArticle $imagearticle = null)
    {
        $this->imagearticle = $imagearticle;

        return $this;
    }

    /**
     * Get imagearticle
     *
     * @return \AD\PlatformBundle\Entity\ImageArticle
     */
    public function getImagearticle()
    {
        return $this->imagearticle;
    }
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->user = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Set slugurl
     *
     * @param string $slugurl
     *
     * @return Article
     */
    public function setSlugurl($slugurl)
    {
        $this->slugurl = $slugurl;

        return $this;
    }

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

    /**
     * Add user
     *
     * @param \AD\UserBundle\Entity\User $user
     *
     * @return Article
     */
    public function addUser(\AD\UserBundle\Entity\User $user)
    {
        $this->user[] = $user;

        return $this;
    }

    /**
     * Remove user
     *
     * @param \AD\UserBundle\Entity\User $user
     */
    public function removeUser(\AD\UserBundle\Entity\User $user)
    {
        $this->user->removeElement($user);
    }

    /**
     * Add imagearticle
     *
     * @param \AD\PlatformBundle\Entity\ImageArticle $imagearticle
     *
     * @return Article
     */
    public function addImagearticle(\AD\PlatformBundle\Entity\ImageArticle $imagearticle)
    {
        $this->imagearticle[] = $imagearticle;
        return $this;
    }

    /**
     * Remove imagearticle
     *
     * @param \AD\PlatformBundle\Entity\ImageArticle $imagearticle
     */
    public function removeImagearticle(\AD\PlatformBundle\Entity\ImageArticle $imagearticle)
    {
        $this->imagearticle->removeElement($imagearticle);
    }
}

here

谢谢你的帮助!

我的控制器:

public function newArticleAction(Request $request)
    {

        $article= new Article();
        $form = $this->get('form.factory')->create(new \AD\PlatformBundle\Form\ArticleType(), $article); 
        if($form->handleRequest($request)->isValid())
        {

            $em = $this->getDoctrine()->getManager();
            $em->persist($article);
            $em->flush();

            $request->getSession()->getFlashBag()->add('notice', 'Annonce enregistrée ! :)');
            return $this->redirect($this->generateUrl('va_platform_blog'));
        }

        return $this->render('ADPlatformBundle:Cars:newarticle.html.twig', array(
            'form' =>$form->createView(),
        ));
    }

我的表格ArticleType:

class ArticleType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('titre1')
            ->add('titre2')
            ->add('description', 'textarea', array('required' => false))
            ->add('imagearticle', 'collection', array(
                'type'          => new ImageArticleType(),
                'allow_add'     => true,
                'allow_delete'  => true,
                'required'      => true,
                'by_reference'  => false,
            ))
        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AD\PlatformBundle\Entity\Article'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'ad_platformbundle_article';
    }
}

ImageArticleType

namespace AD\PlatformBundle\Form;

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

class ImageArticleType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('file', 'file', array('label' => 'Choisir mon images'))
        ;

    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AD\PlatformBundle\Entity\ImageArticle'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'ad_platformbundle_imagearticle';
    }

1 个答案:

答案 0 :(得分:1)

这是解决方案。

在ImageArticle.php中:

/**
 * @var Article
 * @ORM\ManyToOne(targetEntity="AD\PlatformBundle\Entity\Article", inversedBy="imagearticle")
 * @ORM\JoinColumn(nullable=false)
 * @Assert\NotNull()
 */
private $article; //previously $Article

在Article.php中:

/**
 *
 * @ORM\OneToMany(targetEntity="AD\PlatformBundle\Entity\ImageArticle", mappedBy="article", cascade="all", orphanRemoval=true)
 * @Assert\Valid()
 *
 */
private $imagearticle; // remove @ORM\OrderBy({"position" = "ASC"}) since there is no position property

public function __construct()
{
    $this->user = new \Doctrine\Common\Collections\ArrayCollection();
    $this->imagearticle = new \Doctrine\Common\Collections\ArrayCollection(); //instanciate as an ArrayCollection when a new instance of Article is created
}

/**
 * Add imagearticle
 *
 * @param \AD\PlatformBundle\Entity\ImageArticle $imagearticle
 *
 * @return Article
 */
public function addImagearticle(\AD\PlatformBundle\Entity\ImageArticle $imagearticle)
{
    $imagearticle->setArticle($this); //since doctrine only checks owning side you need to do this to keep data in sync
    $this->imagearticle[] = $imagearticle;

    return $this;
}

/**
 * Remove imagearticle
 *
 * @param \AD\PlatformBundle\Entity\ImageArticle $imagearticle
 */
public function removeImagearticle(\AD\PlatformBundle\Entity\ImageArticle $imagearticle)
{
    $imagearticle->setArticle(); //same reason than above
    $this->imagearticle->removeElement($imagearticle);

    return $this;
}

我还建议你删除方法setImagearticle(),因为图像文章是一个集合而不是一个对象,你不应该使用它。

使用camelCase来命名你的变量和方法(因此它应该是$ imageArticle而不是imagearticle)这是一个很好的做法,可以让你的代码更容易阅读。

最后在使用集合时使用复数(即用户而不是用户),这样您就可以立即知道自己在使用什么(另一种良好做法)。