I encountered a problem under symfony3 which has blocked me for a while ... I do not understand this error:
Expected value of type "Doctrine\Common\Collections\Collection|array" for association field "AppBundle\Entity\Project#$participants", got "string" instead.
Here is my entity Project:
class Project
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="projects")
* #ORM\JoinColumn(nullable=false)
*/
private $user;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Participant", mappedBy="project", cascade={"persist", "remove"})
*/
private $participants;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="content", type="text", nullable=true)
*/
private $content;
/**
* #var string
*
* #ORM\Column(name="place", type="string", length=255, nullable=true)
*/
private $place;
/**
* #var \DateTime
*
* #ORM\Column(name="dateEvent", type="datetime", nullable=true)
*/
private $dateEvent;
/**
* #var boolean
*
* #ORM\Column(name="status", type="boolean")
*/
private $status;
/**
* #var boolean
*
* #ORM\Column(name="in_progress", type="boolean")
*/
private $inProgress;
/**
* #var boolean
*
* #ORM\Column(name="accept_list", type="boolean")
*/
private $acceptList;
/**
* #var boolean
*
* #ORM\Column(name="visible_list", type="boolean")
*/
private $visibleList;
/**
* #var boolean
*
* #ORM\Column(name="many_loop", type="boolean")
*/
private $manyLoop;
/**
* #var string
*
* #ORM\Column(name="text_email", type="text", nullable=true)
*/
private $textEmail;
/**
* #var \DateTime
*
* #ORM\Column(name="created", type="datetime")
*/
private $created;
public function __construct()
{
$this->run = false;
$this->status = false;
$this->acceptList = true;
$this->visibleList = true;
$this->inProgress = false;
$this->manyLoop = true;
$this->created = new \Datetime('now');
$this->participants = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
*
* #return Project
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set content
*
* #param string $content
*
* #return Project
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get content
*
* #return string
*/
public function getContent()
{
return $this->content;
}
/**
* Set place
*
* #param string $place
*
* #return Project
*/
public function setPlace($place)
{
$this->place = $place;
return $this;
}
/**
* Get place
*
* #return string
*/
public function getPlace()
{
return $this->place;
}
/**
* Set dateEvent
*
* #param \DateTime $dateEvent
*
* #return Project
*/
public function setDateEvent($dateEvent)
{
$this->dateEvent = $dateEvent;
return $this;
}
/**
* Get dateEvent
*
* #return \DateTime
*/
public function getDateEvent()
{
return $this->dateEvent;
}
/**
* Set status
*
* #param boolean $status
*
* #return Project
*/
public function setStatus($status)
{
$this->status = $status;
return $this;
}
/**
* Get status
*
* #return boolean
*/
public function getStatus()
{
return $this->status;
}
/**
* Set inProgress
*
* #param boolean $inProgress
*
* #return Project
*/
public function setInProgress($inProgress)
{
$this->inProgress = $inProgress;
return $this;
}
/**
* Get inProgress
*
* #return boolean
*/
public function getInProgress()
{
return $this->inProgress;
}
/**
* Set acceptList
*
* #param boolean $acceptList
*
* #return Project
*/
public function setAcceptList($acceptList)
{
$this->acceptList = $acceptList;
return $this;
}
/**
* Get acceptList
*
* #return boolean
*/
public function getAcceptList()
{
return $this->acceptList;
}
/**
* Set visibleList
*
* #param boolean $visibleList
*
* #return Project
*/
public function setVisibleList($visibleList)
{
$this->visibleList = $visibleList;
return $this;
}
/**
* Get visibleList
*
* #return boolean
*/
public function getVisibleList()
{
return $this->visibleList;
}
/**
* Set manyLoop
*
* #param boolean $manyLoop
*
* #return Project
*/
public function setManyLoop($manyLoop)
{
$this->manyLoop = $manyLoop;
return $this;
}
/**
* Get manyLoop
*
* #return boolean
*/
public function getManyLoop()
{
return $this->manyLoop;
}
/**
* Set textEmail
*
* #param string $textEmail
*
* #return Project
*/
public function setTextEmail($textEmail)
{
$this->textEmail = $textEmail;
return $this;
}
/**
* Get textEmail
*
* #return string
*/
public function getTextEmail()
{
return $this->textEmail;
}
/**
* Set created
*
* #param \DateTime $created
*
* #return Project
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set user
*
* #param \AppBundle\Entity\User $user
*
* #return Project
*/
public function setUser(\AppBundle\Entity\User $user)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return \AppBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
/**
* Add participant
*
* #param \AppBundle\Entity\Participant $participant
*
* #return Project
*/
public function addParticipant(\AppBundle\Entity\Participant $participant)
{
$this->participants[] = $participant;
// On lie l'annonce à la candidature
$participant->setProject($this);
return $this;
}
/**
* Remove participant
*
* #param \AppBundle\Entity\Participant $participant
*/
public function removeParticipant(\AppBundle\Entity\Participant $participant)
{
$this->participants->removeElement($participant);
}
/**
* Get participants
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getParticipants()
{
return $this->participants;
}}
My Form:
$builder ->add('participants', ParticipantType::class);
/**
* {#inheritdoc}
*/
public function configureOptions (OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Project',
'step' => 1,
));
}
Form imbricated :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('lastName', TextType::class, array(
'required' => true,
'label' => 'Nom'
))
->add('firstName', TextType::class, array(
'required' => true,
'label' => 'Prénom'
))
->add('email', EmailType::class, array(
'required' => true,
'label' => 'Adresse mail'
));
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => array('registration')
));
}
So here is to summarize my problem, I do not understand the error that Symfony returns, yet from the examples on the internet I do not see why there is a problem here ...
If someone to a solution would be top, because I blocked on this problem for a long time ...
Thank's !
Make sure that you don't forget to add : use Doctrine\Common\Collections\ArrayCollection or use $this->participants = new \Doctrine\Common\Collections\ArrayCollection();
In your FormType you should configure the participants field as a collection of Participant. It should be done using CollectionType like this:
$builder->add('participants', CollectionType::class, array(
'entry_type' => ParticipantType::class,
'allow_add' => true,
...
));
EDIT
According to your data model, the participants Field is a collection of Participant object. As you can see in the error message you presented, an array is expected. The CollectionType will always return an array of the target type.
That is why I suggest you to consider using a CollectionType in your form type. You can learn more about CollectionType here and about Symfony forms in general here
Related
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';
}
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).
I try to setup a User creation form with FOS. There, the user specific language can be choosed from a databasetable (language).
This seems to be a bad solution for the reason that there must be an other way to give a choice between four langueges on user creation form. I'm stucking, and as far as I understand the documentation, theyre talking about website translation (this is my second step but first I need to setup the users).
Is there a nice way to get hteese languages into the creation form: actually, my form looks like
$form = $this->createFormBuilder($user)
->add('firstname', 'text')
->add('usergroups', 'entity', array('class' => 'PrUserBundle:Group','property' => 'name'))
->add('language', 'entity', array('class' => 'PrUserBundle:Language','property' => 'name'))
->add('lastname', 'text')
->add('username', 'text')
->add('email', 'text')
->add('phone', 'text')
->add('password', 'password')
->add('save', 'submit')
->getForm();
It works but with
->add('language', 'entity', array('class' => 'PrUserBundle:Language','property' => 'name'))
Cause an error for the reason that there are no getters and setters for it in my user class.
My User Class also don't know about the language so adding getters will bring no result :(
My User Entity:
<?php
// src/Pr/UserBundle/Entity/User.php
namespace Pr\UserBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="sys_user")
*/
class User extends BaseUser
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="integer", nullable=true)
*/
protected $client;
/**
* #ORM\Column(type="integer", nullable=true)
*/
private $client_id;
/**
* #ORM\Column(type="string", length=16383, nullable=true) //16383 = max varchar utf8
*/
private $imageurl;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
protected $firstname;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
protected $lastname;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $phone;
/**
* #ORM\Column(type="integer", nullable = true)
*/
protected $lock_state;
/**
* #ORM\Column(type="array", nullable=true)
*/
private $locations;
/**
* #ORM\Column(type="array", nullable=true)
*/
private $usergroups;
/**
* #ORM\Column(type="string", length=5, options={"fixed" = true, "default" = "de_DE"})
*/
private $locale = 'de_DE';
/**
* #ORM\Column(type="string", length=32)
*/
private $timezone = 'UTC';
/**
* #ORM\Column(type="array", nullable=true)
*/
private $created='1';
//do not persist!
protected $plain_password;
public function __construct()
{
parent::__construct();
// your own logic
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set client
*
* #param integer $client
* #return User
*/
public function setClient($client)
{
$this->client = $client;
return $this;
}
/**
* Get client
*
* #return integer
*/
public function getClient()
{
return $this->client;
}
/**
* Set client_id
*
* #param integer $clientId
* #return User
*/
public function setClientId($clientId)
{
$this->client_id = $clientId;
return $this;
}
/**
* Get client_id
*
* #return integer
*/
public function getClientId()
{
return $this->client_id;
}
/**
* Set imageurl
*
* #param string $imageurl
* #return User
*/
public function setImageurl($imageurl)
{
$this->imageurl = $imageurl;
return $this;
}
/**
* Get imageurl
*
* #return string
*/
public function getImageurl()
{
return $this->imageurl;
}
/**
* Set firstname
*
* #param string $firstname
* #return User
*/
public function setFirstname($firstname)
{
$this->firstname = $firstname;
return $this;
}
/**
* Get firstname
*
* #return string
*/
public function getFirstname()
{
return $this->firstname;
}
/**
* Set lastname
*
* #param string $lastname
* #return User
*/
public function setLastname($lastname)
{
$this->lastname = $lastname;
return $this;
}
/**
* Get lastname
*
* #return string
*/
public function getLastname()
{
return $this->lastname;
}
/**
* Set phone
*
* #param string $phone
* #return User
*/
public function setPhone($phone)
{
$this->phone = $phone;
return $this;
}
/**
* Get phone
*
* #return string
*/
public function getPhone()
{
return $this->phone;
}
/**
* Set lock_state
*
* #param integer $lockState
* #return User
*/
public function setLockState($lockState)
{
$this->lock_state = $lockState;
return $this;
}
/**
* Get lock_state
*
* #return integer
*/
public function getLockState()
{
return $this->lock_state;
}
/**
* Set locations
*
* #param array $locations
* #return User
*/
public function setLocations($locations)
{
$this->locations = $locations;
return $this;
}
/**
* Get locations
*
* #return array
*/
public function getLanguage()
{
return $this->language;
}
/**
* Get locations
*
* #return array
*/
public function getLocations()
{
return $this->locations;
}
/**
* Set usergroups
*
* #param array $usergroups
* #return User
*/
public function setUsergroups($usergroups)
{
$this->usergroups = $usergroups;
return $this;
}
/**
* Get usergroups
*
* #return array
*/
public function getUsergroups()
{
return $this->usergroups;
}
/**
* Set locale
*
* #param string $locale
* #return User
*/
public function setLocale($locale)
{
$this->locale = $locale;
return $this;
}
/**
* Get locale
*
* #return string
*/
public function getLocale()
{
return $this->locale;
}
/**
* Set timezone
*
* #param string $timezone
* #return User
*/
public function setTimezone($timezone)
{
$this->timezone = $timezone;
return $this;
}
/**
* Get timezone
*
* #return string
*/
public function getTimezone()
{
return $this->timezone;
}
/**
* Set created
*
* #param array $created
* #return User
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* #return array
*/
public function getCreated()
{
return $this->created;
}
}
Hello i have this error when i try to persist my entity :
An exception occurred while executing 'INSERT INTO item_details (item_id, item_type, name, start_date, end_date, description, pre_requisites, picture, acquired_knowledges, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' with params [null, null, "ertret", "09\/01\/2014", "17\/01\/2014", "ter", "trtre", {}, "trtre", null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'item_id' cannot be null
Course entity code :
<?php
namespace Mooc\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Course
*
* #ORM\Table(name="course")
* #ORM\Entity
*/
class Course
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="language_id", type="integer", nullable=false)
*/
private $languageId;
/**
* #var integer
*
* #ORM\Column(name="category_id", type="integer", nullable=false)
*/
private $categoryId;
/**
* #ORM\OneToMany(targetEntity="ItemDetails", mappedBy="course",cascade={"all"})
**/
private $details;
/**
* Constructor
*/
public function __construct()
{
$this->details = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set languageId
*
* #param integer $languageId
* #return Course
*/
public function setLanguageId($languageId)
{
$this->languageId = $languageId;
return $this;
}
/**
* Get languageId
*
* #return integer
*/
public function getLanguageId()
{
return $this->languageId;
}
/**
* Set categoryId
*
* #param integer $categoryId
* #return Course
*/
public function setCategoryId($categoryId)
{
$this->categoryId = $categoryId;
return $this;
}
/**
* Get categoryId
*
* #return integer
*/
public function getCategoryId()
{
return $this->categoryId;
}
/**
* Add details
*
* #param \Mooc\TeacherBundle\Entity\ItemDetails $details
* #return Course
*/
public function addDetail(\Mooc\AdminBundle\Entity\ItemDetails $details)
{
$this->details[] = $details;
return $this;
}
/**
* Add details
*
* #param \Mooc\TeacherBundle\Entity\ItemDetails $details
* #return Course
*/
public function setDetails(\Mooc\AdminBundle\Entity\ItemDetails $details)
{
$this->details[] = $details;
return $this;
}
/**
* Remove details
*
* #param \Mooc\TeacherBundle\Entity\ItemDetails $details
*/
public function removeDetail(\Mooc\AdminBundle\Entity\ItemDetails $details)
{
$this->details->removeElement($details);
}
/**
* Get details
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getDetails()
{
return $this->details;
}
}
Item details entity code :
namespace Mooc\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* ItemDetails
*
* #ORM\Table(name="item_details")
* #ORM\Entity
*/
class ItemDetails
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="item_id", type="integer", nullable=false)
*/
private $itemId;
/**
* #var integer
*
* #ORM\Column(name="item_type", type="integer", nullable=false)
*/
private $itemType;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="start_date", type="string", length=60, nullable=false)
*/
private $startDate;
/**
* #var string
*
* #ORM\Column(name="end_date", type="string", length=60, nullable=false)
*/
private $endDate;
/**
* #var string
*
* #ORM\Column(name="description", type="text", nullable=false)
*/
private $description;
/**
* #var string
*
* #ORM\Column(name="pre_requisites", type="text", nullable=false)
*/
private $preRequisites;
/**
* #var string
*
* #ORM\Column(name="picture", type="string", length=255, nullable=false)
*/
private $picture;
/**
* #var string
*
* #ORM\Column(name="acquired_knowledges", type="text", nullable=false)
*/
private $acquiredKnowledges;
/**
* #var integer
*
* #ORM\Column(name="status", type="integer", nullable=false)
*/
private $status;
/**
* #ORM\ManyToOne(targetEntity="Course", inversedBy="details")
* #ORM\JoinColumn(name="item_id", referencedColumnName="id")
**/
private $course;
/**
* #ORM\OneToMany(targetEntity="Video", mappedBy="itemDetails",cascade={"all"})
**/
private $video;
/**
* Constructor
*/
public function __construct()
{
$this->video = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set itemId
*
* #param integer $itemId
* #return ItemDetails
*/
public function setItemId($itemId)
{
$this->itemId = $itemId;
return $this;
}
/**
* Get itemId
*
* #return integer
*/
public function getItemId()
{
return $this->itemId;
}
/**
* Set itemType
*
* #param integer $itemType
* #return ItemDetails
*/
public function setItemType($itemType)
{
$this->itemType = $itemType;
return $this;
}
/**
* Get itemType
*
* #return integer
*/
public function getItemType()
{
return $this->itemType;
}
/**
* Set name
*
* #param string $name
* #return ItemDetails
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set startDate
*
* #param string $startDate
* #return ItemDetails
*/
public function setStartDate($startDate)
{
$this->startDate = $startDate;
return $this;
}
/**
* Get startDate
*
* #return string
*/
public function getStartDate()
{
return $this->startDate;
}
/**
* Set endDate
*
* #param string $endDate
* #return ItemDetails
*/
public function setEndDate($endDate)
{
$this->endDate = $endDate;
return $this;
}
/**
* Get endDate
*
* #return string
*/
public function getEndDate()
{
return $this->endDate;
}
/**
* Set description
*
* #param string $description
* #return ItemDetails
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set preRequisites
*
* #param string $preRequisites
* #return ItemDetails
*/
public function setPreRequisites($preRequisites)
{
$this->preRequisites = $preRequisites;
return $this;
}
/**
* Get preRequisites
*
* #return string
*/
public function getPreRequisites()
{
return $this->preRequisites;
}
/**
* Set picture
*
* #param string $picture
* #return ItemDetails
*/
public function setPicture($picture)
{
$this->picture = $picture;
return $this;
}
/**
* Get picture
*
* #return string
*/
public function getPicture()
{
return $this->picture;
}
/**
* Set acquiredKnowledges
*
* #param string $acquiredKnowledges
* #return ItemDetails
*/
public function setAcquiredKnowledges($acquiredKnowledges)
{
$this->acquiredKnowledges = $acquiredKnowledges;
return $this;
}
/**
* Get acquiredKnowledges
*
* #return string
*/
public function getAcquiredKnowledges()
{
return $this->acquiredKnowledges;
}
/**
* Set status
*
* #param integer $status
* #return ItemDetails
*/
public function setStatus($status)
{
$this->status = $status;
return $this;
}
/**
* Get status
*
* #return integer
*/
public function getStatus()
{
return $this->status;
}
/**
* Set course
*
* #param \Mooc\AdminBundle\Entity\Course $course
* #return ItemDetails
*/
public function setCourse(\Mooc\AdminBundle\Entity\Course $course = null)
{
$this->course = $course;
return $this;
}
/**
* Get course
*
* #return \Mooc\AdminBundle\Entity\Course
*/
public function getCourse()
{
return $this->course;
}
/**
* Add details
*
* #param \Mooc\TeacherBundle\Entity\ItemDetails $video
* #return Course
*/
public function addVideo(\Mooc\AdminBundle\Entity\Video $video)
{
$this->details[] = $video;
return $this;
}
/**
* Add details
*
* #param \Mooc\TeacherBundle\Entity\ItemDetails $video
* #return Course
*/
public function setVideo(\Mooc\AdminBundle\Entity\Video $video)
{
$this->video[] = $video;
return $this;
}
/**
* Remove details
*
* #param \Mooc\TeacherBundle\Entity\ItemDetails $video
*/
public function removeVideo(\Mooc\AdminBundle\Entity\Video $video)
{
$this->video->removeElement($video);
}
/**
* Get details
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getVideo()
{
return $this->video;
}
}
Video entity code :
namespace Mooc\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Video
*
* #ORM\Table(name="video")
* #ORM\Entity
*/
class Video
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="course_id", type="integer", nullable=false)
*/
private $courseId;
/**
* #var string
*
* #ORM\Column(name="video", type="string", length=255, nullable=false)
*/
private $video;
/**
* #var string
*
* #ORM\Column(name="description", type="text", nullable=false)
*/
private $description;
/**
* #ORM\ManyToOne(targetEntity="ItemDetails")
* #ORM\JoinColumn(name="course_id", referencedColumnName="id")
**/
private $itemDetails;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set courseId
*
* #param integer $courseId
* #return Video
*/
public function setCourseId($courseId)
{
$this->courseId = $courseId;
return $this;
}
/**
* Get courseId
*
* #return integer
*/
public function getCourseId()
{
return $this->courseId;
}
/**
* Set video
*
* #param string $video
* #return Video
*/
public function setVideo($video)
{
$this->video = $video;
return $this;
}
/**
* Get video
*
* #return string
*/
public function getVideo()
{
return $this->video;
}
/**
* Set description
*
* #param string $description
* #return Video
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set itemDetails
*
* #param \Mooc\AdminBundle\Entity\ItemDetails $itemDetails
* #return Video
*/
public function setItemDetails(\Mooc\AdminBundle\Entity\ItemDetails $itemDetails = null)
{
$this->itemDetails = $itemDetails;
return $this;
}
/**
* Get itemDetails
*
* #return \Mooc\AdminBundle\Entity\ItemDetails
*/
public function getItemDetails()
{
return $this->itemDetails;
}
}
Course form code :
namespace Mooc\AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use Doctrine\ORM\EntityRepository;
class CourseType extends AbstractType
{
private $languageId;
public function __construct($languageId) {
$this->languageId=$languageId;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$session = new Session();
$languageId=$session->get('languageId');
$builder
->add('languageId', 'entity', array(
'class' => 'MoocAdminBundle:Language',
'property' => 'name',
'preferred_choices' => array((object)$languageId),
))
->add('categoryId', 'entity', array(
'class' => 'MoocAdminBundle:CourseCategory',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.languageId ='.$this->languageId);
},
))
->add('details', new ItemDetailsType())
->add('submit', 'submit', array('attr' => array('class' => 'btn btn-success btn-large')));
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Mooc\AdminBundle\Entity\Course'
));
}
/**
* #return string
*/
public function getName()
{
return 'mooc_adminbundle_course';
}
}
ItemDetails form :
namespace Mooc\AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ItemDetailsType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('startDate')
->add('endDate')
->add('description')
->add('preRequisites')
->add('picture','file')
->add('acquiredKnowledges')
->add('status')
->add('video', new VideoType())
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Mooc\AdminBundle\Entity\ItemDetails'
));
}
/**
* #return string
*/
public function getName()
{
return 'mooc_adminbundle_itemdetails';
}
}
video Form :
<?php
namespace Mooc\AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class VideoType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('courseId')
->add('video','file')
->add('description','textarea')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Mooc\AdminBundle\Entity\Video'
));
}
/**
* #return string
*/
public function getName()
{
return 'mooc_adminbundle_video';
}
}
Code in controller :
public function courseaddAction() {
$locale=$this->get('session')->get('_locale');
$language=$this->get('doctrine.orm.entity_manager')->getRepository('MoocAdminBundle:Language')->findBy(array('locale'=>$locale));
$languageId=$language[0]->getId();
$form=$this->createForm(new CourseType($languageId));
if ($this->getRequest()->isMethod("POST")) {
$form->HandleRequest($this->getRequest());
//if ($form->isValid()) {
$course = $form->getData();
$this->get('mooc.course')->addCourse($course);
//}
}
return $this->render('MoocTeacherBundle:Default:courseadd.html.twig', array('form'=>$form->createView(),'languageId'=>$languageId));
}
Code in service :
public function addCourse($course) {
$details=$course->getDetails();
$this->em->persist($course);
/*
foreach($course->getDetails() as $details) {
$details->setItemType('course');
$this->em->persist($details);
foreach($details->getVideo() as $video) {
$this->em->persist($video);
}
}
*/
$this->em->flush();
}
You need to set ItemId, in example from form:
$builder
->add('name')
->add('startDate')
->add('itemId') //add this line
->add('endDate')
->add('description')
->add('preRequisites')
->add('picture','file')
->add('acquiredKnowledges')
->add('status')
->add('video', new VideoType())
;
or change nullable value to true
/**
* #var integer
*
* #ORM\Column(name="item_id", type="integer", nullable=true) //here nullable to true
*/
private $itemId;
I'm hoping this is possible using some built-in libraries such as the form builder. I have the following three entities. The one in the middle is almost just a regular join table but it has an extra column with an extra piece of data.
Formula --< FormulaColor >-- Color
FormulaColor has the fields: formula, color, and percentage.
The percentage field is to say what percentage a color makes up of a given formula. A very simple example is that a Formula may be 77% red and 33% blue. My problem is that I want to choose the colors for a Formula, and give them a percentage manually using forms. So I would add (or edit) a certain formula and give it say the color violet (20%) green (45%) and yellow (35%). I do not care about being able to add new colors in the formula add/edit view. I just want to be able to select existing colors. I've been playing around with it for hours with collection and entity types, but no luck.
Got any pointers or tips for me? Will I have to do it manually without the form component etc?
Thanks.
formula form type
class FormulaAddEditType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('code', null, array(
'label' => 'Code'
))
->add('name', null, array(
'label' => 'Name'
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Prism\Portal\CommonBundle\Entity\Formula'
));
}
public function getName()
{
return 'prism_portal_adminbundle_formulaaddedittype';
}
}
Formula Entity
class Formula
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*
* #Serializer\Expose
*/
private $id;
/**
* #var string $code
*
* #ORM\Column(name="code", type="string", length=50, nullable=true)
*
* #Serializer\Expose
*/
private $code;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=50, nullable=true)
*/
private $name;
/**
* #var datetime $createdOn
*
* #Gedmo\Timestampable(on="create")
* #ORM\Column(name="createdOn", type="datetime", nullable=true)
*/
private $createdOn;
/**
* #var datetime $updatedOn
*
* #Gedmo\Timestampable(on="update")
* #ORM\Column(name="updatedOn", type="datetime", nullable=true)
*/
private $updatedOn;
/**
* #var formulaColors
*
* #ORM\OneToMany(targetEntity="FormulaColor", mappedBy="formula")
*/
private $formulaColors;
public function __construct()
{
$this->formulaColors = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set code
*
* #param string $code
*/
public function setCode($code)
{
$this->code = $code;
}
/**
* Get code
*
* #return string
*/
public function getCode()
{
return $this->code;
}
/**
* Set name
*
* #param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set createdOn
*
* #param datetime $createdOn
*/
public function setCreatedOn($createdOn)
{
$this->createdOn = $createdOn;
}
/**
* Get createdOn
*
* #return datetime
*/
public function getCreatedOn()
{
return $this->createdOn;
}
/**
* Set updatedOn
*
* #param datetime $updatedOn
*/
public function setUpdatedOn($updatedOn)
{
$this->updatedOn = $updatedOn;
}
/**
* Get updatedOn
*
* #return datetime
*/
public function getUpdatedOn()
{
return $this->updatedOn;
}
/**
* Add formulaColor
*
* #param FormulaColor $formulaColor
*/
public function addFormulaColor(FormulaColor $formulaColor)
{
$this->formulaColors[] = $formulaColor;
}
/**
* Get formulaColors
*
* #return Doctrine\Common\Collections\Collection
*/
public function getFormulaColors()
{
return $this->formulaColors;
}
}
FormulaColor Entity
/**
* Prism\Portal\CommonBundle\Entity\FormulaColor
*
* #ORM\Table(name="FormulaColor")
* #ORM\Entity
*
* #Serializer\ExclusionPolicy("all")
*/
class FormulaColor
{
/**
* #var integer $formula
*
* #ORM\ManyToOne(targetEntity="Formula", inversedBy="formulaColors")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="formulaId", referencedColumnName="id")
* })
* #ORM\Id
*/
private $formula;
/**
* #var integer color
*
* #ORM\ManyToOne(targetEntity="Color", inversedBy="formulaColors")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="colorId", referencedColumnName="id")
* })
* #ORM\Id
*/
private $color;
/**
* #var decimal percentage
*
* #ORM\Column(type="decimal", precision=5, scale=2, nullable=false)
*/
private $percentage;
/**
* Set percentage
*
* #param decimal $percentage
*/
public function setPercentage($percentage)
{
$this->percentage = $percentage;
}
/**
* Get percentage
*
* #return decimal
*/
public function getPercentage()
{
return $this->percentage;
}
/**
* Set formula
*
* #param Prism\Portal\CommonBundle\Entity\Formula $formula
*/
public function setFormula(\Prism\Portal\CommonBundle\Entity\Formula $formula)
{
$this->formula = $formula;
}
/**
* Get formula
*
* #return Prism\Portal\CommonBundle\Entity\Formula
*/
public function getFormula()
{
return $this->formula;
}
/**
* Set color
*
* #param Prism\Portal\CommonBundle\Entity\Color $color
*/
public function setColor(\Prism\Portal\CommonBundle\Entity\Color $color)
{
$this->color = $color;
}
/**
* Get color
*
* #return Prism\Portal\CommonBundle\Entity\Color
*/
public function getColor()
{
return $this->color;
}
}
Color Entity
/**
* Prism\Portal\CommonBundle\Entity\Color
*
* #ORM\Table(name="Color")
* #ORM\Entity
*
* #Serializer\ExclusionPolicy("all")
*/
class Color
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string $code
*
* #ORM\Column(name="code", type="string", length=50, nullable=true)
*/
private $code;
/**
* #var string $hexColor
*
* #ORM\Column(name="hex_color", type="string", length=50, nullable=true)
*/
private $hexColor;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=50, nullable=true)
*/
private $name;
/**
* #var integer $sortOrder
*
* #ORM\Column(name="sortOrder", type="integer", nullable=true)
*/
private $sortOrder;
/**
* #var datetime $createdOn
*
* #ORM\Column(name="createdOn", type="datetime", nullable=true)
*/
private $createdOn;
/**
* #var datetime $updatedOn
*
* #ORM\Column(name="updatedOn", type="datetime", nullable=true)
*/
private $updatedOn;
/**
* #var $formulaColors
*
* #ORM\OneToMany(targetEntity="FormulaColor", mappedBy="color")
*/
private $formulaColors;
public function __construct()
{
$this->formulaColors = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set code
*
* #param string $code
*/
public function setCode($code)
{
$this->code = $code;
}
/**
* Get code
*
* #return string
*/
public function getCode()
{
return $this->code;
}
/**
* Set name
*
* #param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set sortOrder
*
* #param integer $sortOrder
*/
public function setSortOrder($sortOrder)
{
$this->sortOrder = $sortOrder;
}
/**
* Get sortOrder
*
* #return integer
*/
public function getSortOrder()
{
return $this->sortOrder;
}
/**
* Set createdOn
*
* #param datetime $createdOn
*/
public function setCreatedOn($createdOn)
{
$this->createdOn = $createdOn;
}
/**
* Get createdOn
*
* #return datetime
*/
public function getCreatedOn()
{
return $this->createdOn;
}
/**
* Set updatedOn
*
* #param datetime $updatedOn
*/
public function setUpdatedOn($updatedOn)
{
$this->updatedOn = $updatedOn;
}
/**
* Get updatedOn
*
* #return datetime
*/
public function getUpdatedOn()
{
return $this->updatedOn;
}
/**
* Get formulaColors
*
* #return Doctrine\Common\Collections\Collection
*/
public function getFormulaColors()
{
return $this->formulaColors;
}
/**
* addFormulaColors
*
* #param \Prism\Portal\CommonBundle\Entity\FormulaColor $formulaColor
*/
public function addFormulaColor(\Prism\Portal\CommonBundle\Entity\FormulaColor $formulaColor)
{
$this->formulaColors[] = $formulaColor;
}
/**
* Remove formulaColors
*
* #param \Prism\Portal\CommonBundle\Entity\FormulaColor $formulaColors
*/
public function removeFormulaColor(\Prism\Portal\CommonBundle\Entity\FormulaColor $formulaColors)
{
$this->formulaColors->removeElement($formulaColors);
}
/**
* Set hexColor
*
* #param string $hexColor
* #return Color
*/
public function setHexColor($hexColor)
{
$this->hexColor = $hexColor;
return $this;
}
/**
* Get hexColor
*
* #return string
*/
public function getHexColor()
{
return $this->hexColor;
}
}
I also have a ColorAddEditType form
class ColorAddEditType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('code', null, array(
'label' => 'Code'
))
->add('name', null, array(
'label' => 'Name'
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Prism\Portal\CommonBundle\Entity\Color'
));
}
public function getName()
{
return 'prism_portal_adminbundle_coloraddedittype';
}
}
I've also updated my code according to Ryan's response.
FormulaColorType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('color', new ColorAddEditType());
$builder->add('percent', 'number');
}
FormulaAddEditType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('code', null, array(
'label' => 'Code'
))
->add('name', null, array(
'label' => 'Name'
));
$builder->add('formulaColors', 'collection', array(
'type' => new FormulaColorType(),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
));
}
and now I'm getting use a transformer / set data_class to null exceptions. When I change the one to null, then it says I can change the other to null. When I do that it basically says to change it back. Is it normal that I should have to set up a data transformer for something like this?
Here is the current error I'm getting:
The form's view data is expected to be an instance of class
Prism\Portal\CommonBundle\Entity\Color, but is an instance of class
Prism\Portal\CommonBundle\Entity\FormulaColor. You can avoid this
error by setting the "data_class" option to null or by adding a view
transformer that transforms an instance of class
Prism\Portal\CommonBundle\Entity\FormulaColor to an instance of
Prism\Portal\CommonBundle\Entity\Color.
You should be able to do something like this. It's a fairly common pattern. The tricky bit will be the Javascript, but it won't be too bad. You might need to make your numbers add to 100 using Javascript as well.
FormulaType
public function buildForm(FormBuilder $builder, array $options) {
$builder->add('formulaColors', 'collection', array(
'type' => new FormularColorType(),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
));
}
FormulaColorType
public function buildForm(FormBuilder $builder, array $options) {
$builder->add('color', new ColorType()); // Or similar
$builder->add('percent', 'number');
}
Reading this page I've setup a form to handle PATCH requests.
I've a Player entity:
<?php
namespace Acme\PlayerBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
/**
* Acme\PlayerBundle\Entity\Player
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Acme\PlayerBundle\Entity\PlayerRepository")
*/
class Player
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=255)
* #Assert\NotBlank()
*/
private $name;
/**
* #ORM\ManyToOne(targetEntity="Acme\UserBundle\Entity\User", inversedBy="players")
* #ORM\JoinColumn(nullable=false)
*/
private $owner;
/**
* #ORM\ManyToOne(targetEntity="Acme\TeamBundle\Entity\Team", inversedBy="players")
* #ORM\JoinColumn(nullable=false)
* #Assert\NotBlank()
*/
private $team;
/**
* #var integer $shirtNumber
*
* #ORM\Column(name="shirtNumber", type="smallint")
* #Assert\NotBlank()
*/
private $shirtNumber;
/**
* #var integer $vsid
*
* #ORM\Column(name="vsid", type="integer", nullable=true)
*/
private $vsid;
/**
* #var string $firstname
*
* #ORM\Column(name="firstname", type="string", length=255, nullable=true)
*/
private $firstname;
/**
* #var string $lastname
*
* #ORM\Column(name="lastname", type="string", length=255, nullable=true)
*/
private $lastname;
/**
* #var boolean $deleted
*
* #ORM\Column(name="deleted", type="boolean")
*/
private $deleted = false;
/**
* #var integer $role
*
* #ORM\Column(type="integer", nullable=true)
*/
private $role;
/**
* Create the user salt
*/
public function __construct()
{
//TODO: just for test
$this->uniqueId = substr(uniqid(), 0, 14);
}
/* MANAGED BY DOCTRINE, DON'T EDIT */
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Player
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set shirtNumber
*
* #param integer $shirtNumber
* #return Player
*/
public function setShirtNumber($shirtNumber)
{
$this->shirtNumber = $shirtNumber;
return $this;
}
/**
* Get shirtNumber
*
* #return integer
*/
public function getShirtNumber()
{
return $this->shirtNumber;
}
/**
* Set vsid
*
* #param integer $vsid
* #return Player
*/
public function setVsid($vsid)
{
$this->vsid = $vsid;
return $this;
}
/**
* Get vsid
*
* #return integer
*/
public function getVsid()
{
return $this->vsid;
}
/**
* Set firstname
*
* #param string $firstname
* #return Player
*/
public function setFirstname($firstname)
{
$this->firstname = $firstname;
return $this;
}
/**
* Get firstname
*
* #return string
*/
public function getFirstname()
{
return $this->firstname;
}
/**
* Set lastname
*
* #param string $lastname
* #return Player
*/
public function setLastname($lastname)
{
$this->lastname = $lastname;
return $this;
}
/**
* Get lastname
*
* #return string
*/
public function getLastname()
{
return $this->lastname;
}
/**
* Set deleted
*
* #param boolean $deleted
* #return Player
*/
public function setDeleted($deleted)
{
$this->deleted = $deleted;
return $this;
}
/**
* Get deleted
*
* #return boolean
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Set role
*
* #param integer $role
* #return Player
*/
public function setRole($role)
{
$this->role = $role;
return $this;
}
/**
* Get role
*
* #return integer
*/
public function getRole()
{
return $this->role;
}
/**
* Set owner
*
* #param Acme\UserBundle\Entity\User $owner
* #return Player
*/
public function setOwner(\Acme\UserBundle\Entity\User $owner)
{
$this->owner = $owner;
return $this;
}
/**
* Get owner
*
* #return Acme\UserBundle\Entity\User
*/
public function getOwner()
{
return $this->owner;
}
/**
* Set team
*
* #param Acme\TeamBundle\Entity\Team $team
* #return Player
*/
public function setTeam(\Acme\TeamBundle\Entity\Team $team)
{
$this->team = $team;
return $this;
}
/**
* Get team
*
* #return Acme\TeamBundle\Entity\Team
*/
public function getTeam()
{
return $this->team;
}
}
and a Team entity:
<?php
namespace Acme\TeamBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Acme\TeamBundle\Entity\Team
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Acme\TeamBundle\Entity\TeamRepository")
*/
class Team
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $uniqueId
*
* #ORM\Column(name="uniqueId", type="string", length=15)
*/
private $uniqueId;
/**
* #ORM\ManyToOne(targetEntity="Acme\UserBundle\Entity\User", inversedBy="teams")
* #ORM\JoinColumn(nullable=false)
*/
private $owner;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=50)
* #Assert\NotBlank()
*/
private $name;
/**
* #var string $homeColor
*
* #ORM\Column(name="homeColor", type="string", length=7, nullable=true)
*/
private $homeColor;
/**
* #var string $awayColor
*
* #ORM\Column(name="awayColor", type="string", length=7, nullable=true)
*/
private $awayColor;
/**
* #var string $homeShirt
*
* #ORM\Column(name="homeShirt", type="string", length=50, nullable=true)
*/
private $homeShirt;
/**
* #var string $awayShirt
*
* #ORM\Column(name="awayShirt", type="string", length=50, nullable=true)
*/
private $awayShirt;
/**
* #var string $teamLogo
*
* #ORM\Column(name="teamLogo", type="string", length=50, nullable=true)
*/
private $teamLogo;
/**
* #var boolean $deleted
*
* #ORM\Column(name="deleted", type="boolean")
*/
private $deleted = false;
/**
* #ORM\OneToMany(targetEntity="Acme\PlayerBundle\Entity\Player", mappedBy="team", cascade={"persist", "remove"})
*/
private $players;
/**
* #ORM\OneToMany(targetEntity="Acme\MatchBundle\Entity\Match", mappedBy="homeTeam")
*/
private $homeMatches;
/**
* #ORM\OneToMany(targetEntity="Acme\MatchBundle\Entity\Match", mappedBy="awayTeam")
*/
private $awayMatches;
/**
* Create the user salt
*/
public function __construct()
{
$this->players = new ArrayCollection();
$this->homeMatches = new ArrayCollection();
$this->awayMatches = new ArrayCollection();
//TODO: just for test
$this->uniqueId = substr(uniqid(), 0, 14);
}
public function getMatches()
{
return array_merge($this->awayMatches->toArray(), $this->homeMatches->toArray());
}
/* MANAGED BY DOCTRINE, DON'T EDIT */
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set uniqueId
*
* #param string $uniqueId
* #return Team
*/
public function setUniqueId($uniqueId)
{
$this->uniqueId = $uniqueId;
return $this;
}
/**
* Get uniqueId
*
* #return string
*/
public function getUniqueId()
{
return $this->uniqueId;
}
/**
* Set name
*
* #param string $name
* #return Team
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set homeColor
*
* #param string $homeColor
* #return Team
*/
public function setHomeColor($homeColor)
{
$this->homeColor = $homeColor;
return $this;
}
/**
* Get homeColor
*
* #return string
*/
public function getHomeColor()
{
return $this->homeColor;
}
/**
* Set awayColor
*
* #param string $awayColor
* #return Team
*/
public function setAwayColor($awayColor)
{
$this->awayColor = $awayColor;
return $this;
}
/**
* Get awayColor
*
* #return string
*/
public function getAwayColor()
{
return $this->awayColor;
}
/**
* Set homeShirt
*
* #param string $homeShirt
* #return Team
*/
public function setHomeShirt($homeShirt)
{
$this->homeShirt = $homeShirt;
return $this;
}
/**
* Get homeShirt
*
* #return string
*/
public function getHomeShirt()
{
return $this->homeShirt;
}
/**
* Set awayShirt
*
* #param string $awayShirt
* #return Team
*/
public function setAwayShirt($awayShirt)
{
$this->awayShirt = $awayShirt;
return $this;
}
/**
* Get awayShirt
*
* #return string
*/
public function getAwayShirt()
{
return $this->awayShirt;
}
/**
* Set teamLogo
*
* #param string $teamLogo
* #return Team
*/
public function setTeamLogo($teamLogo)
{
$this->teamLogo = $teamLogo;
return $this;
}
/**
* Get teamLogo
*
* #return string
*/
public function getTeamLogo()
{
return $this->teamLogo;
}
/**
* Set deleted
*
* #param boolean $deleted
* #return Team
*/
public function setDeleted($deleted)
{
$this->deleted = $deleted;
return $this;
}
/**
* Get deleted
*
* #return boolean
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Add players
*
* #param Acme\PlayerBundle\Entity\Player $players
* #return Team
*/
public function addPlayer(\Acme\PlayerBundle\Entity\Player $players)
{
$this->players[] = $players;
return $this;
}
/**
* Remove players
*
* #param Acme\PlayerBundle\Entity\Player $players
*/
public function removePlayer(\Acme\PlayerBundle\Entity\Player $players)
{
$this->players->removeElement($players);
}
/**
* Get players
*
* #return Doctrine\Common\Collections\Collection
*/
public function getPlayers()
{
return $this->players;
}
/**
* Add homeMatches
*
* #param Acme\MatchBundle\Entity\Match $homeMatches
* #return Team
*/
public function addHomeMatche(\Acme\MatchBundle\Entity\Match $homeMatches)
{
$this->homeMatches[] = $homeMatches;
return $this;
}
/**
* Remove homeMatches
*
* #param Acme\MatchBundle\Entity\Match $homeMatches
*/
public function removeHomeMatche(\Acme\MatchBundle\Entity\Match $homeMatches)
{
$this->homeMatches->removeElement($homeMatches);
}
/**
* Get homeMatches
*
* #return Doctrine\Common\Collections\Collection
*/
public function getHomeMatches()
{
return $this->homeMatches;
}
/**
* Add awayMatches
*
* #param Acme\MatchBundle\Entity\Match $awayMatches
* #return Team
*/
public function addAwayMatche(\Acme\MatchBundle\Entity\Match $awayMatches)
{
$this->awayMatches[] = $awayMatches;
return $this;
}
/**
* Remove awayMatches
*
* #param Acme\MatchBundle\Entity\Match $awayMatches
*/
public function removeAwayMatche(\Acme\MatchBundle\Entity\Match $awayMatches)
{
$this->awayMatches->removeElement($awayMatches);
}
/**
* Get awayMatches
*
* #return Doctrine\Common\Collections\Collection
*/
public function getAwayMatches()
{
return $this->awayMatches;
}
/**
* Set owner
*
* #param Acme\UserBundle\Entity\User $owner
* #return Team
*/
public function setOwner(\Acme\UserBundle\Entity\User $owner)
{
$this->owner = $owner;
return $this;
}
/**
* Get owner
*
* #return Acme\UserBundle\Entity\User
*/
public function getOwner()
{
return $this->owner;
}
}
Now I've created a player form class with the app/console and I've edited the team field to be an instance of the Team entity, this way:
<?php
namespace Acme\PlayerBundle\Form;
use Acme\TeamBundle\Entity\TeamRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class PlayerType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('shirtNumber')
->add('firstname')
->add('lastname')
->add('role')
->add('team', 'entity', array(
'class' => 'AcmeTeamBundle:Team',
'query_builder' => function(TeamRepository $er) {
$query = $er->createQueryBuilder('t');
return $query;
}
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\PlayerBundle\Entity\Player',
'csrf_protection' => false
));
}
public function getName()
{
return 'player';
}
}
And this is the relevant part of my controller:
/**
* Create a new player
*
* #Route(".{_format}", name="api_player_create")
* #Method("POST")
* #ApiDoc(
* description="Create a new player",
* statusCodes={
* 201="Player created and informations are returned",
* 400="Missing informations",
* 403="The user isn't authorized"
* },
* input="Acme\PlayerBundle\Form\PlayerType",
* return="Acme\PlayerBundle\Entity\Player"
* )
*
* #return Renders the player just created
*/
public function createPlayerAction()
{
return $this->processForm(new Player());
}
/**
* Edit a player
*
* #param integer $id The id of the player to be created
*
* #Route("/{id}.{_format}", name="api_player_patch", requirements={ "id": "\d+" })
* #Method("PATCH")
* #ApiDoc(
* description="Edit a player",
* statusCodes={
* 200="Player is updated",
* 400="Missing informations",
* 403="The user isn't authorized"
* },
* input="Acme\PlayerBundle\Form\PlayerType",
* return="Acme\PlayerBundle\Entity\Player"
* )
*
* #return Renders the player just edited
*/
public function editPlayerAction(Player $player)
{
if ($player->getOwner() != $this->getUser()) {
throw new ApiException\PermissionDeniedException;
}
return $this->processForm($player);
}
/**
* Function to handle a form to create/edit a player
*
* #param Player $player The player to be created or edited
*
* #return Api Response
*/
private function processForm(Player $player)
{
/**
* Check if the player is new (to be created) or we're editing a player
*/
$statusCode = is_null($player->getId()) ? 201 : 200;
$form = $this->createForm(new PlayerType(), $player);
$form->bind($this->getRequest());
if ($form->isValid()) {
if($player->getTeam()->getOwner() != $this->getUser()) {
throw new ApiException\PermissionDeniedException;
}
$player->setOwner($this->getUser());
$this->entityManager->persist($player);
$this->entityManager->flush();
return $this->apiResponse->getResponse($player, $statusCode);
}
return $this->apiResponse->getResponse($form, 400, 'Missing arguments');
}
The player creation works fine, the player edit doesn't, when the user makes the api request, passing the ID in the url and the name of the player I get:
Catchable Fatal Error: Argument 1 passed to Acme\PlayerBundle\Entity\Player::setTeam() must be an instance of Acme\TeamBundle\Entity\Team, null given, called in /Volumes/Dati/Users/alessandro/Sites/acme-api/vendor/symfony/symfony/src/Symfony/Component/Form/Util/PropertyPath.php on line 538 and defined in /Volumes/Dati/Users/alessandro/Sites/acme-api/src/Acme/PlayerBundle/Entity/Player.php line 278
Seems that form is trying to set the Team to null, why?
I've tried both sending and not the team as the form parameters but it doesn't work.
Any clue?
Figured it out that null unsent fields in the form is the default behaviour in symfony.
There is an open request for partial form binding in symfony. For now a guy created a form event subscriber that adds the missing fields with the actual values:
https://gist.github.com/3720535
This is his code:
<?php
namespace Foo;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
/**
* Changes Form->bind() behavior so that it treats not set values as if they
* were sent unchanged.
*
* Use when you don't want fields to be set to NULL when they are not displayed
* on the page (or to implement PUT/PATCH requests).
*/
class PatchSubscriber implements EventSubscriberInterface
{
public function onPreBind(FormEvent $event)
{
$form = $event->getForm();
$clientData = $event->getData();
$clientData = array_replace($this->unbind($form), $clientData ?: array());
$event->setData($clientData);
}
/**
* Returns the form's data like $form->bind() expects it
*/
protected function unbind($form)
{
if ($form->hasChildren()) {
$ary = array();
foreach ($form->getChildren() as $name => $child) {
$ary[$name] = $this->unbind($child);
}
return $ary;
} else {
return $form->getClientData();
}
}
static public function getSubscribedEvents()
{
return array(
FormEvents::PRE_BIND => 'onPreBind',
);
}
}
to add to the form you have to edit the buildForm method in the form class:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$subscriber = new PatchSubscriber();
$builder->addEventSubscriber($subscriber);
$builder->add('name');
....
}
In this case you're ok to use the PATCH REST requests to edit an entity just by the sent fields