Reputation: 63
I'm stuck with this problem. I try to upload one or more picture for one entity with a collection but when I submit my form I've got this error :
Symfony\Component\Validator\ConstraintViolation
Object(Symfony\Component\Form\Form).data.imagearticle[0].Article = null
It's because in my entity ImageArticle I put this :
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;
}
But when I remove this Assert\NotNull my error is "Column article_id cannot be null"
This is my Article entity :
<?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);
}
}
Thx for your help!
My controller :
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(),
));
}
And my form 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';
}
Upvotes: 0
Views: 943
Reputation: 682
Here is the solution.
In ImageArticle.php:
/**
* @var Article
* @ORM\ManyToOne(targetEntity="AD\PlatformBundle\Entity\Article", inversedBy="imagearticle")
* @ORM\JoinColumn(nullable=false)
* @Assert\NotNull()
*/
private $article; //previously $Article
In 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;
}
I also recommend you to remove method setImagearticle() since image article is a collection and not an object, you should not have to use it.
Use camelCase to name your variable and method (so it should be $imageArticle and not imagearticle) this is a good practice to make your code more readable by others.
Finally use plural when you are working with collections (i.e. users instead of user) so you immediatly know what you are working with (another good practice).
Upvotes: 1