I have two entities:
TicketEntity :
/**
* #ORM\MappedSuperclass()
*/
class Ticket implements TicketInterface
{
const DIR_UPLOAD = 'TicketUpload';
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Attachment", mappedBy="ticket", cascade={"remove"}, orphanRemoval=true)
*/
protected $attachments;
/**
* Ticket constructor.
*/
public function __construct()
{
$this->attachments = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
/**
* Add attachments
*
* #param Attachment $attachments
* #return Ticket
*/
public function addAttachment(Attachment $attachments)
{
$this->attachments[] = $attachments;
return $this;
}
/**
* Remove attachments
*
* #param Attachment $attachments
*/
public function removeAttachment(Attachment $attachments)
{
$this->attachments->removeElement($attachments);
}
/**
* Get attachments
*
* #return Collection
*/
public function getAttachments()
{
return $this->attachments;
}
}
AttachmentEntity:
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\AttachmentRepository")
* #ORM\Table(name="ticket_attachments")
*/
class Attachment
{
const DIR_UPLOAD = 'TicketUpload';
/**
* #var int
*
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var string
* #ORM\Column(type="text", nullable=true)
*/
private $name;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Ticket", inversedBy="attachments")
* #ORM\JoinColumn(name="ticket_id", referencedColumnName="id", nullable=true)
*/
protected $ticket;
/**
* #Assert\File(
* maxSize = "300k",
* mimeTypes = {"application/pdf", "application/x-pdf", "text/plain", "application/msword",
* "application/vnd.ms-excel", "image/jpeg", "image/x-citrix-jpeg", "image/png", "image/x-citrix-png", "image/x-png", "image/gif"},
* mimeTypesMessage = "Liste de formats de fichiers acceptés : .pdf,.txt,.doc,.xls,.jpg,.png,.gif"
* )
*/
private $attachmentFile;
/**
* #ORM\Column(type="string", nullable=true)
*
*/
private $attachment;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
public function getName()
{
return $this->name;
}
public function setName($name): self
{
$this->name = $name;
return $this;
}
public function getTicket(): ?Ticket
{
return $this->ticket;
}
public function setTicket(Ticket $ticket): void
{
$this->ticket = $ticket;
}
/**
* #return mixed
*/
public function getAttachment(): ?string
{
return $this->attachment;
}
public function setAttachment($attachment): self
{
$this->attachment = $attachment;
return $this;
}
public function getAttachmentFile(): ?UploadedFile
{
return $this->attachmentFile;
}
/**
* #param $attachmentFile
* #return Ticket
*/
public function setAttachmentFile($attachmentFile): self
{
$this->attachmentFile = $attachmentFile;
return $this;
}
public function getAttachmentWebPath()
{
return self::DIR_UPLOAD . '/' . $this->getAttachment();
}
}
My goal is that a ticket can have several attachments.
And I have this error:
The association AppBundle\Entity\Attachment#ticket refers to the
inverse side field AppBundle\Entity\Ticket#attachments which does not
exist.
I don't know where I'm wrong... Anyone know ?
Regards
mapped superclasses are really inconvenient. really. (emphasis mine)
A mapped superclass cannot be an entity, it is not query-able and
persistent relationships defined by a mapped superclass must be
unidirectional (with an owning side only). This means that One-To-Many
associations are not possible on a mapped superclass at all.
Furthermore Many-To-Many associations are only possible if the mapped
superclass is only used in exactly one entity at the moment. For
further support of inheritance, the single or joined table inheritance
features have to be used.
so, you're not technically doing something wrong, it just isn't supported at all. The error message produced isn't helpful at all though...
Related
I have an entity Voucher that contain a custom operation name add_voucher:
<?php
/**
* #ApiResource(
* collectionOperations={
* "add_voucher"={
* "access_control"="is_granted('ROLE_COMMERCIAL')",
* "method"="POST",
* "path"="/vouchers/add-new",
* "controller"=AddVoucherAction::class,
* "denormalization_context"={
* "groups"={"add_new_voucher"}
* },
* "validation_groups"={"Default", "add_voucher_validation"}
* },
* }
* )
* #ORM\Entity(repositoryClass="App\Repository\VoucherRepository", repositoryClass=VoucherRepository::class)
*/
class Voucher
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #Groups("add_new_voucher")
* #ORM\Column(type="string", length=255, unique=true)
*/
private $code;
/**
* #Groups("add_new_voucher")
* #ORM\Column(type="integer")
*/
private $discount;
/**
* #Groups("add_new_voucher")
* #ORM\Column(type="datetime")
*/
private $starts_at;
public function getDiscount()
{
return $this->discount;
}
public function setDiscount($discount): void
{
$this->discount = $discount;
}
public function getId(): ?int
{
return $this->id;
}
public function getCode(): ?string
{
return $this->code;
}
public function setCode(string $code): self
{
$this->code = $code;
return $this;
}
public function getStartsAt(): ?\DateTimeInterface
{
return $this->starts_at;
}
public function setStartsAt(\DateTimeInterface $starts_at): self
{
$this->starts_at = $starts_at;
return $this;
}
}
I added the denormalization group to code,discount,starts_at, I Later to validate this columns in operations to do so I need to add it first in the denormalization context but in the swagger it show only
the code and discount properties
It is because of the spelling combination of your $starts_at property and getStartsAt() getter. Basically, Symfony serializer use yours getters to access private properties.
Just replace either your property by $starstAt or add an underscore to your getter.
Take a look at this;
I have two entities in my code: Session and SessionPicture.
There is a OneToOne relationship between Session and SessionPicture. SessionPicture is the mapping entity and Session is the inverse one.
Session has an attribute called "Slug", which is generated thanks to the StofDoctrineExtensionsBundle https://github.com/stof/StofDoctrineExtensionsBundle, and using the Gedmo\Sluggable annotation.
I have a form to create a Session (so a SessionType), and this SessionType embeds a SessionPictureType. The SessionPicture class contains a file attribute (UploadedFile class) and I have used LifecycleEvents (PostPersist/PostUpdate) to upload the file of the SessionPicture, and give it the "slug" property of the related Session when I save it.
My issue is that when I try to change another property of my SessionPicture (let's say "alt") and give it the value of the "slug" of the session , I cannot do it in the PostPersist Lifecycle and then save it to my database, because this event takes place after the onFlush, which is too late. I have to do it in the PrePersist Lifecyle. But then the "slug" of my session is not available yet, because it is generated during the onFlush by the extension.
So how can I get the slug of the related session in the prePersist lifecyle?
(PS: I have a found a solution, which is to persist the session in my controller, flush with the Manager, and then to persist again and redo a flush() but it is not very elegant).
Please find my code below:
/**
* Session
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="MyBundle\Entity\SessionRepository")
* #ORM\HasLifecycleCallbacks()
*/
class Session
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* #ORM\OneToOne(targetEntity="MyBundle\Entity\SessionPicture", cascade={"persist", "remove"}, mappedBy="session")
* #ORM\JoinColumn(name="session_picture_id", referencedColumnName="id", nullable=true)
*/
private $sessionPicture;
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set sessionPicture
*
* #param \MyBundle\Entity\SessionPicture $sessionPicture
*
* #return Session
*/
public function setSessionPicture(MyBundle\Entity\SessionPicture $sessionPicture = null)
{
$this->sessionPicture = $sessionPicture;
return $this;
}
/**
* Get sessionPicture
*
* #return \MyBundle\Session\SessionPicture
*/
public function getSessionPicture()
{
return $this->sessionPicture;
}
And my SessionPicture code:
/**
* #var string
*
* #ORM\Column(name="alt", type="string", length=255, nullable=true)
*/
private $alt;
/**
* #var string
*
* #ORM\Column(name="path", type="string", length=255, nullable=true)
*/
private $path;
/**
* #ORM\OneToOne(targetEntity="MyBundle\Entity\Session", inversedBy="sessionPicture")
*/
private $session;
public $file;
private $fileNameForRemove;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set extension
*
* #param string $extension
*
* #return SessionPicture
*/
public function setExtension($extension)
{
$this->extension = $extension;
return $this;
}
/**
* Get extension
*
* #return string
*/
public function getExtension()
{
return $this->extension;
}
/**
* Set alt
*
* #param string $alt
*
* #return SessionPicture
*/
public function setAlt($alt)
{
$this->alt = $alt;
return $this;
}
/**
* Get alt
*
* #return string
*/
public function getAlt()
{
return $this->alt;
}
/**
* Set path
*
* #param string $path
*
* #return SessionPicture
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}
/**
* Get path
*
* #return string
*/
public function getPath()
{
return $this->path;
}
/**
* Set session
*
* #param \MyBundle\Entity\Session $session
*
* #return SessionPicture
*/
public function setSession(\NyBundle\Entity\Session $session = null)
{
$this->session = $session;
return $this;
}
/**
* Get session
*
* #return \MyBundle\Entity\Session
*/
public function getSession()
{
return $this->session;
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function preUpload()
{
if($this->file === null)
return ;
$extension = $this->file->guessExtension();
$this->extension = (string)$extension;
My issue is below, I cannot get the slug before the flush of the session
$this->alt = $this->getSession()->getSlug();
}
/**
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload()
{
But here, I can get the slug because my session has already been flushed and the slug generated
$this->alt = $this->getSession()->getSlug();
$this->path = $this->alt.'.'.$this->extension;
if ($this->file === null)
return ;
$this->file->move($this->getUploadRootDir(), $this->path);
unset($this->file);
}
Finally, here is an extract my controller code:
$form->handlerequest($request);
$validator = $this->get('validator');
$errorList = $validator->validate($session);
if (count($errorList) == 0)
{
$em = $this->getDoctrine()->getManager();
$em->persist($session);
$em->flush();
$em->persist($session);
$em->flush();
As you can see, I had to persist the $session and to flush it once, so that the slug is generated at the flush. Then persist again so that the slug is now available for the "alt" property of the SessionPicture at the prePersist n2, and flush again to save the alt property. But it is not very clean.
Thanks for any hel or advice. Thanks.
I am new to Symfony2 and Doctrine, i am stuck a little bit. Error receiving while saving to the database.
An exception occurred while executing 'INSERT INTO tho_provider (provid_name, provid_logo, provid_logo_path, created_time, provider_created_by) VALUES (?, ?, ?, ?, ?)' with params ["test", {}, "qwwwww", "2015-08-11 16:03:15", null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'provider_created_by' cannot be null
I have the form where i am only getting provider name input and logo, rest is i am handling in the controller, Including provider_created_by which gets null just after the flush, before the flush command its showing the value.
public function createAction(Request $request)
{
$user = $this->getUser();
$entity = new Provider();
$entity->setProvidLogoPath("qwwwww");
$entity->setProviderCreatedBy($user);
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if ($form->isValid()) {
//$entity->setCreatedBy($user);
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('provider_show', array('id' => $entity->getId())));
}
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
I have entities, PROVIDER and USER.
User's can create many provider and providers only belongs to one user. One to many relationship.
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* Provider
*
* #ORM\Table(name="tho_provider")
* #ORM\Entity(repositoryClass="AppBundle\Entity\ProviderRepository")
* #Vich\Uploadable
* #ORM\HasLifecycleCallbacks()
*/
class Provider
{
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="providers")
* #ORM\JoinColumn(name="provider_created_by", referencedColumnName="id")
*/
protected $users;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
* #Assert\NotBlank()
* #ORM\Column(name="provid_name", type="string", length=255)
*/
private $providName;
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="general_image", fileNameProperty="provid_logo")
*
* #var File
*/
private $imageFile;
/**
* #var string
*
* #ORM\Column(name="provid_logo", type="string", length=255)
*/
private $providLogo;
/**
* #var string
*
* #ORM\Column(name="provid_logo_path", type="string", length=255)
*/
private $providLogoPath;
/**
* #var \DateTime
* #Assert\Type("\DateTime")
* #ORM\Column(name="created_time", type="datetime")
*/
private $createdTime;
/**
* #var integer
*
* #ORM\Column(name="provider_created_by", type="integer")
*/
public $providerCreatedBy;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set providName
*
* #param string $providName
* #return Provider
*/
public function setProvidName($providName)
{
$this->providName = $providName;
return $this;
}
/**
* Get providName
*
* #return string
*/
public function getProvidName()
{
return $this->providName;
}
/**
* Set providLogo
*
* #param string $providLogo
* #return Provider
*/
public function setProvidLogo($providLogo)
{
$this->providLogo = $providLogo;
return $this;
}
/**
* Get providLogo
*
* #return string
*/
public function getProvidLogo()
{
return $this->providLogo;
}
/**
* Set providLogoPath
*
* #param string $providLogoPath
* #return Provider
*/
public function setProvidLogoPath($providLogoPath)
{
$this->providLogoPath = $providLogoPath;
return $this;
}
/**
* Get providLogoPath
*
* #return string
*/
public function getProvidLogoPath()
{
return $this->providLogoPath;
}
/**
* Set createdTime
*
* #param \DateTime $createdTime
* #return Provider
*/
public function setCreatedTime($createdTime)
{
$this->createdTime = $createdTime;
return $this;
}
/**
* Get createdTime
*
* #return \DateTime
*/
public function getCreatedTime()
{
return $this->createdTime;
}
/**
* Set users
*
* #param \AppBundle\Entity\User $users
* #return Provider
*/
public function setUsers(\AppBundle\Entity\User $users = null)
{
$this->users = $users;
return $this;
}
/**
* Get users
*
* #return \AppBundle\Entity\User
*/
public function getUsers()
{
return $this->users;
}
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* #param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
*/
public function setImageFile(File $image = null)
{
$this->imageFile = $image;
if ($image) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTime('now');
}
}
/**
* #return File
*/
public function getImageFile()
{
return $this->imageFile;
}
/**
* #ORM\PrePersist
*/
public function setCreatedTimeValue()
{
$this->createdTime = new \DateTime();
}
/**
* Set providerCreatedBy
*
* #param integer $providerCreatedBy
* #return Provider
*/
public function setProviderCreatedBy($providerCreatedBy)
{
$this->providerCreatedBy = $providerCreatedBy;
return $this;
}
/**
* Get providerCreatedBy
*
* #return integer
*/
public function getProviderCreatedBy()
{
return $this->providerCreatedBy;
}
}
USER:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Doctrine\Common\Collections\ArrayCollection;
/**
* User
*
* #ORM\Table(name="tho_user")
* #ORM\Entity(repositoryClass="AppBundle\Entity\UserRepository")
* #UniqueEntity(fields="email",message = "This email already exist.")
* #UniqueEntity(fields = "username",message = "This username already taken")
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* #ORM\OneToMany(targetEntity="Provider", mappedBy="user")
*/
protected $providers;
public function __construct()
{
$this->providers = new ArrayCollection();
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*#Assert\NotBlank(message="Username is required!")
* #Assert\Length(min=3,minMessage="Minimum 3 characters long.")
* #ORM\Column(name="username", type="string", length=255)
*/
protected $username;
/**
* #var string
*
*
* #ORM\Column(name="password", type="string", length=255)
*/
private $password;
/**
* #var array
*
* #ORM\Column(name="roles",type="json_array")
*/
private $roles = array();
/**
* #var bool
*
* #ORM\Column(name="is_active",type="boolean")
*/
private $isActive = true;
/**
* #var string
*#Assert\NotBlank()
* #Assert\Email
* #ORM\Column(name="email",type="string", length=255)
*/
private $email;
/**
* #var string
*#Assert\NotBlank()
*
* #ORM\Column(name="first_name",type="string", length=255)
*/
private $firstName;
/**
* #var string
*#Assert\NotBlank()
* #ORM\Column(name="last_name",type="string", length=255)
*/
private $lastName;
/**
* #var string
*
* #ORM\Column(name="iata",type="string", length=255)
*/
private $iata;
/**
* #var string
*
* #ORM\Column(name="job_title",type="string", length=255)
*/
private $jobTitle;
/**
* #var string
*
* #ORM\Column(name="agency_phone",type="string", length=255)
*/
private $agencyPhone;
/**
* #var string
*
* #ORM\Column(name="emergency_mobile",type="string", length=255)
*/
private $emergencyMobile;
/**
* Storing password temporarily
* #Assert\NotBlank()
* #Assert\Length(min=6,minMessage="Minimum 6 characters long.")
* #var string
*/
private $plainPassword;
/**
* Get id
*
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* #param string $username
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* #return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set password
*
* #param string $password
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
public function getRoles()
{
$roles = $this->roles;
$roles[] = 'ROLE_ADMIN';
return array_unique($roles);
}
public function setRoles(array $roles)
{
$this->roles = $roles;
return $this;
}
public function eraseCredentials()
{
$this->setPlainPassword(null);
}
public function getSalt()
{
return null;
}
/**
* #return boolean
*/
public function isIsActive()
{
return $this->isActive;
}
/**
* #param boolean $isActive
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
}
/**
* Checks whether the user's account has expired.
*
* Internally, if this method returns false, the authentication system
* will throw an AccountExpiredException and prevent login.
*
* #return bool true if the user's account is non expired, false otherwise
*
* #see AccountExpiredException
*/
public function isAccountNonExpired()
{
return true;
}
/**
* Checks whether the user is locked.
*
* Internally, if this method returns false, the authentication system
* will throw a LockedException and prevent login.
*
* #return bool true if the user is not locked, false otherwise
*
* #see LockedException
*/
public function isAccountNonLocked()
{
return true;
}
/**
* Checks whether the user's credentials (password) has expired.
*
* Internally, if this method returns false, the authentication system
* will throw a CredentialsExpiredException and prevent login.
*
* #return bool true if the user's credentials are non expired, false otherwise
*
* #see CredentialsExpiredException
*/
public function isCredentialsNonExpired()
{
return true;
}
/**
* Checks whether the user is enabled.
*
* Internally, if this method returns false, the authentication system
* will throw a DisabledException and prevent login.
*
* #return bool true if the user is enabled, false otherwise
*
* #see DisabledException
*/
public function isEnabled()
{
return true;
}
/**
* Get isActive
*
* #return boolean
*/
public function getIsActive()
{
return $this->isActive;
}
/**
* Set email
*
* #param string $email
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* (PHP 5 >= 5.1.0)<br/>
* String representation of object
* #link http://php.net/manual/en/serializable.serialize.php
* #return string the string representation of the object or null
*/
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->password
));
}
/**
* (PHP 5 >= 5.1.0)<br/>
* Constructs the object
* #link http://php.net/manual/en/serializable.unserialize.php
* #param string $serialized <p>
* The string representation of the object.
* </p>
* #return void
*/
public function unserialize($serialized)
{
list(
$this->id,
$this->username,
$this->password
) = unserialize($serialized);
}
/**
* #return string
*/
public function getFirstName()
{
return $this->firstName;
}
/**
* #param string $firstName
*/
public function setFirstName($firstName)
{
$this->firstName = $firstName;
}
/**
* #return string
*/
public function getLastName()
{
return $this->lastName;
}
/**
* #param string $lastName
*/
public function setLastName($lastName)
{
$this->lastName = $lastName;
}
/**
* #return string
*/
public function getIata()
{
return $this->iata;
}
/**
* #param string $iata
*/
public function setIata($iata)
{
$this->iata = $iata;
}
/**
* #return string
*/
public function getJobTitle()
{
return $this->jobTitle;
}
/**
* #param string $jobTitle
*/
public function setJobTitle($jobTitle)
{
$this->jobTitle = $jobTitle;
}
/**
* #return string
*/
public function getAgencyPhone()
{
return $this->agencyPhone;
}
/**
* #param string $agencyPhone
*/
public function setAgencyPhone($agencyPhone)
{
$this->agencyPhone = $agencyPhone;
}
/**
* #return string
*/
public function getEmergencyMobile()
{
return $this->emergencyMobile;
}
/**
* #param string $emergencyMobile
*/
public function setEmergencyMobile($emergencyMobile)
{
$this->emergencyMobile = $emergencyMobile;
}
/**
* #return string
*/
public function getPlainPassword()
{
return $this->plainPassword;
}
/**
* #param string $plainPassword
*/
public function setPlainPassword($plainPassword)
{
$this->plainPassword = $plainPassword;
}
/**
* Set provider
*
* #param \AppBundle\Entity\Provider $provider
* #return User
*/
public function setProvider(\AppBundle\Entity\Provider $provider = null)
{
$this->provider = $provider;
return $this;
}
/**
* Get provider
*
* #return \AppBundle\Entity\Provider
*/
public function getProvider()
{
return $this->provider;
}
/**
* Add providers
*
* #param \AppBundle\Entity\Provider $providers
* #return User
*/
public function addProvider(\AppBundle\Entity\Provider $providers)
{
$this->providers[] = $providers;
return $this;
}
/**
* Remove providers
*
* #param \AppBundle\Entity\Provider $providers
*/
public function removeProvider(\AppBundle\Entity\Provider $providers)
{
$this->providers->removeElement($providers);
}
/**
* Get providers
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getProviders()
{
return $this->providers;
}
}
Your metadata is
/**
* #var integer
*
* #ORM\Column(name="provider_created_by", type="integer")
*/
public $providerCreatedBy;
but you are passing an object (probably null):
$user = $this->getUser();
/* ... */
$entity->setProviderCreatedBy($user);
And the setter has no type hint:
public function setProviderCreatedBy($providerCreatedBy)
{
$this->providerCreatedBy = $providerCreatedBy;
return $this;
}
You must change your mapping of $providerCreatedBy to ManyToOne with User entity.
Check if your user has been logged in, $this->getUser() returns null if user is anonymous, also I think you should change your mapping info for providerCreatedBy field, from column type integer to ManyToOne relationship with User class..
I use symfony2.4 and KNP doctrine behaviors translatable.
I have entity Site (for ID, host, enabled) and entity SiteTranslation (for translated fields: name, descriptions, …).
I use query to get results
$qb = $this->createQueryBuilder('s')
->addSelect('translation') // to eager fetch translations (optional)
->leftJoin('s.translations', 'translation') // or innerJoin ?
->orderBy('s.root', 'ASC')
->addOrderBy('s.lft', 'ASC');
I would like to print result in Twig. For ID, host and enabled fields from Site entity it's easy:
{{ item.id }}
But I can't print translated fields (name, description, …)
{{ item.name }}
It doesn't work.
Error message:
ContextErrorException: Warning: call_user_func_array() expects parameter 1 to be a valid >callback, class 'Net\ConBundle\Entity\SiteTranslation' does not have a method 'name' in >D:\Users...\vendor\knplabs\doctrine->behaviors\src\Knp\DoctrineBehaviors\Model\Translatable\TranslatableMethods.php line 140
Getters and setters for translatable fields are in SiteTranslation entity.
UPDATE:
I still didn't find a solution for an error.
Here is Site entity:
<?php
namespace Pnet\ConlocoBundle\Entity;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
/**
* #UniqueEntity("host", message="site.host.unique", groups={"edit"})
* #Gedmo\Tree(type="nested")
* #ORM\Entity(repositoryClass="Pnet\ConlocoBundle\Entity\Repository\SiteRepository")
* #ORM\Table(name="site")
*/
class Site
{
use ORMBehaviors\Translatable\Translatable; // knp translatable strategy
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=40, unique=true)
* #Assert\NotBlank(message="site.host.notBlank", groups={"edit"})
* #Assert\Length(max = "40", maxMessage = "site.host.maxLength", groups={"edit"})
*/
protected $host;
/**
* #ORM\Column(type="string", length=255, nullable=true)
* #Assert\Image()
*/
protected $image;
/**
* #ORM\Column(type="boolean")
* #Assert\Choice(choices = {"1", "0"}, message = "site.isDefault.choice", groups={"edit"})
*/
protected $isDefault;
/**
* #ORM\Column(type="boolean")
* #Assert\Choice(choices = {"1", "0"}, message = "site.enabled.choice", groups={"edit"})
*/
protected $enabled;
/**
* #ORM\Column(type="string", length=64, nullable=true)
*/
protected $analytics;
/**
* #Gedmo\TreeLeft
* #ORM\Column(name="lft", type="integer")
*/
private $lft;
/**
* #Gedmo\TreeLevel
* #ORM\Column(name="lvl", type="integer")
*/
private $lvl;
/**
* #Gedmo\TreeRight
* #ORM\Column(name="rgt", type="integer")
*/
private $rgt;
/**
* #Gedmo\TreeRoot
* #ORM\Column(name="root", type="integer", nullable=true)
*/
private $root;
/**
* #Gedmo\TreeParent
* #ORM\ManyToOne(targetEntity="Site", inversedBy="children")
* #ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $parent;
/**
* #ORM\OneToMany(targetEntity="Site", mappedBy="parent")
* #ORM\OrderBy({"lft" = "ASC"})
*/
private $children;
private $file;
public $idByFilter;
public $nameByFilter;
/**
* Proxy translations (Knp/Doctrine Behaviors)
* An extra feature allows you to proxy translated fields of a translatable entity.
* You can use it in the magic __call method of you translatable entity so that when
* you try to call getName (for example) it will return you the translated value
* of the name for current locale:
*/
public function __call($method, $arguments)
{
return $this->proxyCurrentLocaleTranslation($method, $arguments);
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set host
*
* #param string $host
* #return Site
*/
public function setHost($host)
{
$this->host = $host;
return $this;
}
/**
* Get host
*
* #return string
*/
public function getHost()
{
return $this->host;
}
/**
* Set isDefault
*
* #param boolean $isDefault
* #return Site
*/
public function setIsDefault($isDefault)
{
$this->isDefault = $isDefault;
return $this;
}
/**
* Get isDefault
*
* #return boolean
*/
public function getIsDefault()
{
return $this->isDefault;
}
/**
* Set enabled
*
* #param boolean $enabled
* #return Site
*/
public function setEnabled($enabled)
{
$this->enabled = $enabled;
return $this;
}
/**
* Get enabled
*
* #return boolean
*/
public function getEnabled()
{
return $this->enabled;
}
/**
* Set analytics
*
* #param string $analytics
* #return Site
*/
public function setAnalytics($analytics)
{
$this->analytics = $analytics;
return $this;
}
/**
* Get analytics
*
* #return string
*/
public function getAnalytics()
{
return $this->analytics;
}
/**
* Get ID from Filter
*
* #return string
*/
public function getIdByFilter()
{
return $this->idByFilter;
}
/**
* Get name from Filter
*
* #return string
*/
public function getNameByFilter()
{
return $this->nameByFilter;
}
/**
* Set image
*
* #param string $image
* #return Site
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
/**
* Set file
*
* #param string $file
* #return Site
*/
public function setFile($file)
{
$this->file = $file;
return $this;
}
/**
* Get file
*
* #return string
*/
public function getFile()
{
return $this->file;
}
/**
*
* Tree functions
*/
public function setParent(Site $parent = null)
{
$this->parent = $parent;
}
public function getParent()
{
return $this->parent;
}
public function getRoot()
{
return $this->root;
}
public function getLvl()
{
return $this->lvl;
}
public function getChildren()
{
return $this->children;
}
public function getLft()
{
return $this->lft;
}
public function getRgt()
{
return $this->rgt;
}
/**
* Add a method to the entity class that shows the name indented by nesting level
*/
public function getLeveledName()
{
return str_repeat(
html_entity_decode(' ', ENT_QUOTES, 'UTF-8'),
($this->getLvl()) * 3
) . $this->getName();
}
public function getLeveledPosition()
{
return str_repeat(
html_entity_decode(' ', ENT_QUOTES, 'UTF-8'),
($this->getLvl()) * 3
);
}
}
And here is SiteTranslation entity:
namespace Pnet\ConlocoBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
/**
* #ORM\Entity
*/
class SiteTranslation
{
use ORMBehaviors\Translatable\Translation;
/**
* #ORM\Column(type="string", length=60)
* #Assert\NotBlank(message="site.name.notBlank", groups={"edit"})
* #Assert\Length(max = "60", maxMessage = "site.name.maxLength", groups={"edit"})
*/
protected $name;
/**
* #ORM\Column(type="string", length=100)
* #Assert\NotBlank(message="site.title.notBlank", groups={"edit"})
* #Assert\Length(max = "100", maxMessage = "site.title.maxLength", groups={"edit"})
*/
protected $title;
/**
* #ORM\Column(type="string", length=200)
* #Assert\NotBlank(message="site.longTitle.notBlank", groups={"edit"})
* #Assert\Length(max = "200", maxMessage = "site.longTitle.maxLength", groups={"edit"})
*/
protected $longTitle;
/**
* #ORM\Column(type="string", length=250, nullable=true)
* #Assert\Length(max = "250", maxMessage = "site.keywords.maxLength", groups={"edit"})
*/
protected $keywords;
/**
* #ORM\Column(type="string", length=500, nullable=true)
* #Assert\Length(max = "500", maxMessage = "site.description.maxLength", groups={"edit"})
*/
protected $description;
/**
* Set name
*
* #param string $name
* #return Site
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set title
*
* #param string $title
* #return Site
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set longTitle
*
* #param string $longTitle
* #return Site
*/
public function setLongTitle($longTitle)
{
$this->longTitle = $longTitle;
return $this;
}
/**
* Get longTitle
*
* #return string
*/
public function getLongTitle()
{
return $this->longTitle;
}
/**
* Set keywords
*
* #param string $keywords
* #return Site
*/
public function setKeywords($keywords)
{
$this->keywords = $keywords;
return $this;
}
/**
* Get keywords
*
* #return string
*/
public function getKeywords()
{
return $this->keywords;
}
/**
* Set description
*
* #param string $description
* #return Site
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
}
TL;DR:
As a (probably dirty) workaround, use
{{ item.getName }}
in your Twig template instead of
{{ item.name }}
Explanation:
I came across the same issue and i think that this should be considered a bug in the Knp DoctrineBehaviors documentation when used with Twig. When you call this in your Twig template :
{{ item.name }}
This is what Twig does behind the scenes to get the name property :
try to get the name public property of the item object
if not found, checks for the name public method of the item object
if not found, checks for the getName() public method of the "item" object
if not found, checks for the __call() magic method (and calls it with the name parameter)
The problem here is step 4. The magic __call() method that you defined (as recommended by the official DoctrineBehaviors documentation) is called with the name parameter instead of getName. It then calls the proxyCurrentLocaleTranslation() method who tries to call the name public method of your translation class. Of course, it doesn't exist because you only have a getName() method.
See this issue in Twig : https://github.com/twigphp/Twig/issues/342
By using directly the {{ item.getName }} code in Twig, the proper method name will be called.
This work for me:
public function __call($method, $arguments)
{
try {
return $this->proxyCurrentLocaleTranslation($method, $arguments);
} catch (\Symfony\Component\Debug\Exception\ContextErrorException $e) {
return $this->proxyCurrentLocaleTranslation('get' . ucfirst($method), $arguments);
}
}
You haven't moved all the translatable properties/methods to your <Name>Translation class.
The exception clearly states that there is no name/getName method in your SiteTranslation class.
Please read my answer over here to see how Knp\DoctrineBehaviors's magic translation proxy is used correctly.
I'm lost in a complexe relation (for me). I've a entity project for an entity client and you can attach users to a project. When i try to add a project without users, no problem. But, when i try to add a project and users Sf2 display this error :
Entity of type Intranet\IntranetBundle\Entity\ProjectUser is missing an assigned ID for field 'project'. The identifier generation strategy for this entity requires the ID field to be populated before EntityManager#persist() is called. If you want automatically generated identifiers instead you need to adjust the metadata mapping accordingly.
I'm understand it's angry because the project_id is null. But i don't know why it's null.
My Project.php
namespace Intranet\IntranetBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Project
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Intranet\IntranetBundle\Entity\ProjectRepository")
*/
class Project
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
* #Assert\NotBlank(
* message = "The field cannot be empty"
* )
*/
private $name;
/**
* #Gedmo\Slug(fields={"name"})
* #ORM\Column(length=255, unique=true)
*/
private $slug;
/**
* #var string
*
* #ORM\Column(name="contact_client", type="text", nullable=true)
*/
private $contactClient;
/**
* #var string
*
* #ORM\Column(name="technologies", type="string", length=255, nullable=true)
*/
private $technologies;
/**
* #var string
*
* #ORM\Column(name="languages", type="string", length=255, nullable=true)
*/
private $languages;
/**
* #var string
*
* #ORM\Column(name="extern", type="text", nullable=true)
*/
private $extern;
/**
* #var string
*
* #ORM\Column(name="url_prod", type="string", length=255, nullable=true)
*/
private $urlProd;
/**
* #var string
*
* #ORM\Column(name="url_staging", type="text", nullable=true)
*/
private $urlStaging;
/**
* #var string
*
* #ORM\Column(name="url_dev", type="text", nullable=true)
*/
private $urlDev;
/**
* #var string
*
* #ORM\Column(name="hosting_company", type="string", length=255, nullable=true)
*/
private $hostingCompany;
/**
* #var string
*
* #ORM\Column(name="hosting_type", type="string", length=255, nullable=true)
*/
private $hostingType;
/**
* #var string
*
* #ORM\Column(name="hosting_manager", type="text", nullable=true)
*/
private $hostingManager;
/**
* #var string
*
* #ORM\Column(name="ssh", type="text", nullable=true)
*/
private $ssh;
/**
* #var string
*
* #ORM\Column(name="ftp", type="text", nullable=true)
*/
private $ftp;
/**
* #var string
*
* #ORM\Column(name="db", type="text", nullable=true)
*/
private $db;
/**
* #var string
*
* #ORM\Column(name="emails", type="text", nullable=true)
*/
private $emails;
/**
* #var string
*
* #ORM\Column(name="cms", type="text", nullable=true)
*/
private $cms;
/**
* #var string
*
* #ORM\Column(name="web_services", type="text", nullable=true)
*/
private $webServices;
/**
* #var string
*
* #ORM\Column(name="comment", type="text", nullable=true)
*/
private $comment;
/**
* #ORM\ManyToOne(targetEntity="Intranet\IntranetBundle\Entity\Client", inversedBy="projects")
* #ORM\JoinColumn(nullable=false)
*/
private $client;
/**
* #ORM\OneToMany(targetEntity="Intranet\IntranetBundle\Entity\ProjectUser", mappedBy="project", cascade={"persist"})
*/
private $projectUsers;
public function __construct()
{
$this->projectUsers = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Project
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set slug
*
* #param string $slug
* #return Client
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* Set contactClient
*
* #param string $contactClient
* #return Project
*/
public function setContactClient($contactClient)
{
$this->contactClient = $contactClient;
return $this;
}
/**
* Get contactClient
*
* #return string
*/
public function getContactClient()
{
return $this->contactClient;
}
/**
* Set technologies
*
* #param string $technologies
* #return Project
*/
public function setTechnologies($technologies)
{
$this->technologies = $technologies;
return $this;
}
/**
* Get technologies
*
* #return string
*/
public function getTechnologies()
{
return $this->technologies;
}
/**
* Set languages
*
* #param string $languages
* #return Project
*/
public function setLanguages($languages)
{
$this->languages = $languages;
return $this;
}
/**
* Get languages
*
* #return string
*/
public function getLanguages()
{
return $this->languages;
}
/**
* Set extern
*
* #param string $extern
* #return Project
*/
public function setExtern($extern)
{
$this->extern = $extern;
return $this;
}
/**
* Get extern
*
* #return string
*/
public function getExtern()
{
return $this->extern;
}
/**
* Set urlProd
*
* #param string $urlProd
* #return Project
*/
public function setUrlProd($urlProd)
{
$this->urlProd = $urlProd;
return $this;
}
/**
* Get urlProd
*
* #return string
*/
public function getUrlProd()
{
return $this->urlProd;
}
/**
* Set urlStaging
*
* #param string $urlStaging
* #return Project
*/
public function setUrlStaging($urlStaging)
{
$this->urlStaging = $urlStaging;
return $this;
}
/**
* Get urlStaging
*
* #return string
*/
public function getUrlStaging()
{
return $this->urlStaging;
}
/**
* Set urlDev
*
* #param string $urlDev
* #return Project
*/
public function setUrlDev($urlDev)
{
$this->urlDev = $urlDev;
return $this;
}
/**
* Get urlDev
*
* #return string
*/
public function getUrlDev()
{
return $this->urlDev;
}
/**
* Set hostingCompany
*
* #param string $hostingCompany
* #return Project
*/
public function setHostingCompany($hostingCompany)
{
$this->hostingCompany = $hostingCompany;
return $this;
}
/**
* Get hostingCompany
*
* #return string
*/
public function getHostingCompany()
{
return $this->hostingCompany;
}
/**
* Set hostingType
*
* #param string $hostingType
* #return Project
*/
public function setHostingType($hostingType)
{
$this->hostingType = $hostingType;
return $this;
}
/**
* Get hostingType
*
* #return string
*/
public function getHostingType()
{
return $this->hostingType;
}
/**
* Set hostingManager
*
* #param string $hostingManager
* #return Project
*/
public function setHostingManager($hostingManager)
{
$this->hostingManager = $hostingManager;
return $this;
}
/**
* Get hostingManager
*
* #return string
*/
public function getHostingManager()
{
return $this->hostingManager;
}
/**
* Set ssh
*
* #param string $ssh
* #return Project
*/
public function setSsh($ssh)
{
$this->ssh = $ssh;
return $this;
}
/**
* Get ssh
*
* #return string
*/
public function getSsh()
{
return $this->ssh;
}
/**
* Set ftp
*
* #param string $ftp
* #return Project
*/
public function setFtp($ftp)
{
$this->ftp = $ftp;
return $this;
}
/**
* Get ftp
*
* #return string
*/
public function getFtp()
{
return $this->ftp;
}
/**
* Set db
*
* #param string $db
* #return Project
*/
public function setDb($db)
{
$this->db = $db;
return $this;
}
/**
* Get db
*
* #return string
*/
public function getDb()
{
return $this->db;
}
/**
* Set emails
*
* #param string $emails
* #return Project
*/
public function setEmails($emails)
{
$this->emails = $emails;
return $this;
}
/**
* Get emails
*
* #return string
*/
public function getEmails()
{
return $this->emails;
}
/**
* Set cms
*
* #param string $cms
* #return Project
*/
public function setCms($cms)
{
$this->cms = $cms;
return $this;
}
/**
* Get cms
*
* #return string
*/
public function getCms()
{
return $this->cms;
}
/**
* Set webServices
*
* #param string $webServices
* #return Project
*/
public function setWebServices($webServices)
{
$this->webServices = $webServices;
return $this;
}
/**
* Get webServices
*
* #return string
*/
public function getWebServices()
{
return $this->webServices;
}
/**
* Set comment
*
* #param string $comment
* #return Project
*/
public function setComment($comment)
{
$this->comment = $comment;
return $this;
}
/**
* Get comment
*
* #return string
*/
public function getComment()
{
return $this->comment;
}
/**
* Set client
*
* #param \Intranet\IntranetBundle\Entity\Client $client
* #return Project
*/
public function setClient(\Intranet\IntranetBundle\Entity\Client $client)
{
$this->client = $client;
return $this;
}
/**
* Get client
*
* #return \Intranet\IntranetBundle\Entity\Client
*/
public function getClient()
{
return $this->client;
}
public function addProjectUser(\Intranet\IntranetBundle\Entity\ProjectUser $projectUser)
{
$this->projectUsers[] = $projectUser;
}
public function removeProjectUser(\Intranet\IntranetBundle\Entity\ProjectUser $projectUser)
{
$this->projectUsers->removeElement($projectUser);
}
public function getProjectUsers()
{
return $this->projectUsers;
}
}
My ProjectUser.php
namespace Intranet\IntranetBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class ProjectUser
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Intranet\IntranetBundle\Entity\Project", inversedBy="projectUsers")
*/
private $project;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Intranet\UserBundle\Entity\User")
*/
private $user;
/**
* #ORM\Column(name="profil", type="smallint")
*/
private $profil;
public function setProject(\Intranet\IntranetBundle\Entity\Project $project)
{
$project->addProjectUser($this);
$this->project = $project;
}
public function getProject()
{
return $this->project;
}
public function setUser(\Intranet\UserBundle\Entity\User $user)
{
$this->user = $user;
}
public function getUser()
{
return $this->user;
}
public function setProfil($profil)
{
$this->profil = $profil;
}
public function getProfil()
{
return $this->profil;
}
}
profil = smallint for the job of the user (1=manager, 2=designer, ...)
My ProjectController (addAction)
public function addAction()
{
$project = new Project;
$form = $this->createForm(new ProjectType, $project);
$request = $this->get('request');
if ($request->getMethod() == 'POST') {
$form->bind($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($project);
$em->flush();
foreach ($form->get('projectUsers')->getData() as $u) {
$u->setProject($project);
$em->persist($u);
}
$em->flush();
$this->get('session')->getFlashBag()->add('success', 'The project : '. $project->getName() .' has been added');
return $this->redirect($this->generateUrl('clients_list'));
}
}
return $this->render('IntranetIntranetBundle:Project:add_project.html.twig', array(
'form' => $form->createView()
));
}
Thanks for your help
Well, first of all, you shouldn't specify #ORM\Id annotation on every foreign key in your ProjectUser entity - it is for primary keys.
Then you should declare column join on foreign key fields:
/**
* #ORM\ManyToOne(targetEntity="Intranet\IntranetBundle\Entity\Project", inversedBy="projectUsers")
* #ORM\JoinColumn(name="project_id", referencedColumnName="id")
*/
private $project;
/**
* #ORM\ManyToOne(targetEntity="Intranet\IntranetBundle\Entity\User", inversedBy="projects")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
You also should have a field like
class User
{
// ...
/**
* #ORM\OneToMany(targetEntity="Intranet\IntranetBundle\Entity\ProjectUser", mappedBy="user")
*/
private $projects;
// ...
}
Finally, to add user to project, I suggest you embed a ProjectUserType form with user selection into ProjectType form. In your controller, you can have something like
public function addAction()
{
$project = new Project;
$projectUser = new ProjectUser();
$projectUser->setProject($project);
$project->addProjectUser($projectUser);
$form = $this->createForm(new ProjectType, $project);
// ...
And in form ProjectUserType
class ProjectUserType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('user', 'entity', array(
'class' => 'Intranet:IntranetBundle:User'
));
// ...
Hope this helps at least a little bit.
When you code : $em->persist($project);
$project is equal to $project = new Project; (don't you have forget '()' ?)
Actually the $projet is empty... To do this, I think you forget to code :
$project = $form->getData();