Serialization of UploadedFile is not allowed - symfony

I'm trying to upload a file via vichuploader bundle on my Users entity.
Using hwioauthbundle that implements UserInterface, and i think the errors comes from that bundle...
So every time i try to uplod a file i got this exception :
Serialization of 'Symfony\Component\HttpFoundation\File\UploadedFile'
is not allowed
I already tried this solution but also same exception.
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider as BaseClass;
use Symfony\Component\Security\Core\User\UserInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthUser;
/**
* Users
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UsersRepository")
*
*/
class Users extends OAuthUser
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="first_name", type="string", length=255)
*/
private $firstName;
/**
* #var string
*
* #ORM\Column(name="last_name", type="string", length=255)
*/
private $lastName;
/**
* #var string
*
* #ORM\Column(name="civility", type="string", length=255, nullable=true)
*/
private $civility;
/**
* #var string
*
* #ORM\Column(name="avatar", type="string", length=255, nullable=true)
*/
private $avatar;
/**
* #var string
*
* #ORM\Column(name="qualification", type="string", length=255, nullable=true)
*/
private $qualification;
/**
* #var string
*
* #ORM\Column(name="level", type="string", length=255, nullable=true)
*/
private $level;
/**
* #var \DateTime
*
* #ORM\Column(name="birth_date", type="date", nullable=true)
*/
private $birthDate;
/**
* #var \DateTime
*
* #ORM\Column(name="hiring_date", type="date", nullable=true)
*/
private $hiringDate;
/**
* #var string
*
* #ORM\Column(name="country", type="string", length=255, nullable=true)
*/
private $country;
/**
* #var string
*
* #ORM\Column(name="city", type="string", length=255, nullable=true)
*/
private $city;
/**
* #var string
*
* #ORM\Column(name="linkedin_profil", type="string", length=255, nullable=true)
*/
private $linkedinProfil;
/**
* #var string
*
* #ORM\Column(name="web_site", type="string", length=255, nullable=true)
*/
private $webSite;
/**
* #var \DateTime
*
* #ORM\Column(name="date_last_cnx", type="datetimetz", nullable=true)
*/
private $dateLastCnx;
/**
*
* #ORM\OneToOne(targetEntity="AppBundle\Entity\Files",cascade={"persist"})
* #ORM\JoinColumn(name="file_id", referencedColumnName="id")
*/
public $cv;
/** #ORM\Column(name="google_id", type="string", length=255, nullable=true) */
private $google_id;
Files.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* Files
* #Vich\Uploadable
* #ORM\Table(name="files")
* #ORM\Entity(repositoryClass="AppBundle\Repository\FilesRepository")
*/
class Files
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="product_image", fileNameProperty="imageName", size="imageSize")
*
* #var File
*/
protected $imageFile;
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
protected $imageName;
public function getId()
{
return $this->id;
}
/**
* 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
*
* #return Product
*/
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 \DateTimeImmutable();
}
return $this;
}
/**
* #return File|null
*/
public function getImageFile()
{
return $this->imageFile;
}
/**
* #param string $imageName
*
* #return Product
*/
public function setImageName($imageName)
{
$this->imageName = $imageName;
return $this;
}
/**
* #return string|null
*/
public function getImageName()
{
return $this->imageName;
}
}
My form Userstype:
use AppBundle\Form\FilesType;
->add('cv',FilesType::class)
My form Filestype:
-> add('imageFile',
VichFileType::class, [
'required' => false,
'allow_delete' => true,
'download_link' => true,
'label' => false,
]);

You are serializing ImageFile entity within this code that's why you are getting the error , try removing that and add updatedAt field so that doctrine can track changes on the entity:
/**
* Files
* #ORM\Table(name="files")
* #ORM\Entity(repositoryClass="AppBundle\Repository\FilesRepository")
* #Vich\Uploadable
*/
class Files implements \Serializable
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="product_image", fileNameProperty="imageName", size="imageSize")
*
* #var File
*/
protected $imageFile;
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
protected $imageName;
/**
* #ORM\Column(type="datetime")
*
* #var string
*/
protected $updatedAt;
public function getId()
{
return $this->id;
}
/**
* 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
*
* #return Product
*/
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 \DateTimeImmutable();
}
return $this;
}
/**
* #return File|null
*/
public function getImageFile()
{
return $this->imageFile;
}
/**
* #param string $imageName
*
* #return Product
*/
public function setImageName($imageName)
{
$this->imageName = $imageName;
return $this;
}
/**
* #return string|null
*/
public function getImageName()
{
return $this->imageName;
}
/** #see \Serializable::serialize() */
public function serialize()
{
return serialize(array(
$this->id,
$this->imageName,
));
}
/** #see \Serializable::unserialize() */
public function unserialize($serialized)
{
list (
$this->id,
) = unserialize($serialized);
}
/**
* #return string
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* #param string $updatedAt
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
}
}

for Symfony5
Class User implement UserInterface
public function __serialize(): array
{
return [
'id' => $this->id,
'email' => $this->email,
//......
];
}
public function __unserialize(array $serialized): User
{
$this->id = $serialized['id'];
$this->email = $serialized['email'];
// .....
return $this;
}

Check this out, one of your Users's relation has an UploadedFile property, which is essentially a File aka a filestream which aren't allowed to be serialized. Therefore you need to specify what you want to serialized:
https://symfony.com/doc/3.3/security/entity_provider.html
Basically you only neeed to serialized id, username and password (three is an example code on the above page)

Related

Use php-imap classes to parse new mails from server, with Symfony 2.7

I'm working on Symfony 2.7. I have to create a mail client to retrieve and send mails from the mail server (IMAP protocol); to do this, I used the php-imap classes, with a bundle (included with composer). But I'm not sure about the way I should use them : Do I extend the classes to represent my Mail and Mailbox objects, or should I create new classes from scratch ?
I don't want to manipulate IMAP straight from my controllers, I think it would be too long to process. Is that right?
Is it a good idea to create a "watcher" (periodic command executed by cron) to parse new mails every 2 minutes or so, create new mails entity from them, and send the waiting ones?
Could I do that while extending the php-imap classes? This way I would use one class only? But wouldn't that be too heavy to store for the database ?
What's the correct way to fetch only new mails ? Do I have to use a specific function, like imap_check, or do I do that by a search criteria (like date from the last check) ? I tried with criteria "NEW", but that was unsuccessful.
Also, the mailboxes I have to parse are quite heavy. I tried to make a search in one of them with "ALL" criteria, but it's really long to process ! Am I doing it right ? Do I just have to be patient ?
Here's what I did for the "watcher" function :
use PhpImap\Mailbox as ImapMailbox;
class GetNewMailsCommand extends ContainerAwareCommand
{
$em = $this->getContainer()->get('doctrine')->getEntityManager();
$mailboxes = $em->getRepository('MIPMailBundle:MailBox')->findAllActive();
foreach ($mailboxes as $mailbox){
$imapBox = new ImapMailbox('{'.$mailbox->getServer().':143/notls/norsh/novalidate-cert}INBOX', $mailbox->getAdress(), $mailbox->getPassword());
if ($mailbox->getMails() == null || empty($mailbox->getMails())){
$mailsIds = $imapBox->searchMailbox('ALL');
if(!$mailsIds) {
$output->writeln($mailbox->getAdress() . " is empty");
}
} else {
$mailsIds = $imapBox->searchMailbox('NEW');
if(!$mailsIds) {
$output->writeln("No new mail for " . $mailbox->getAdress());
}
}
foreach ($mailsIds as $mailId){
$imapMail = $imapBox->getMail($mailId);
$mail = new Mail($mailbox, false);
$mail->setSubject($imapMail->subject);
$mail->setSender($imapMail->fromAddress);
$mail->setCc($imapMail->cc);
$mail->setBcc($imapMail->bcc);
$mail->setToString($imapMail->toString);
$mail->setContent($imapMail->textPlain);
$mail->setDate(new \DateTime($imapMail->date));
foreach ($imapMail->to as $toAddress){
$mail->addRecipient($toAddress);
}
$em->persist($mail);
}
}
$em->flush();
And here's my entities :
class MailBox
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var
*
* #ORM\OneToOne(targetEntity="\MIP\CRMBundle\Entity\Agency", inversedBy="mailBox", cascade={"persist"})
* #ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true)
*/
private $user;
/**
* #var Agency
*
* #ORM\ManyToMany(targetEntity="\MIP\CRMBundle\Entity\Agency", inversedBy="mailBoxShared")
* #ORM\JoinTable(name="mailbox_shared")
*/
private $sharedTo;
/**
* #var
*
* #ORM\OneToMany(targetEntity="Mail", mappedBy="mailBox")
*/
private $mails;
/**
* #var boolean
*
* #ORM\Column(name="active", type="boolean")
*/
private $active;
/**
* #var string
*
* #ORM\Column(name="adress", type="string", length=255)
*/
private $adress;
/**
* #var string
*
* #ORM\Column(name="server", type="string", length=255)
*/
private $server;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255)
*/
private $password;
/**
* #var integer
*
* #ORM\Column(name="port", type="integer")
*/
private $port;
/**
* MailBox constructor.
*/
public function __construct()
{
$this->sharedTo = new ArrayCollection();
$this->mails = new ArrayCollection();
}
class Mail
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="sender", type="string", length=255)
*/
private $sender;
/**
* #var array
*
* #ORM\Column(name="recipients", type="json_array", nullable=true)
*/
private $recipients;
/**
* #var string
*
* #ORM\Column(name="toString", type="string", nullable=true)
*/
private $toString;
/**
* #var array
*
* #ORM\Column(name="cc", type="json_array", nullable=true)
*/
private $cc;
/**
* #var array
*
* #ORM\Column(name="bcc", type="json_array", nullable=true)
*/
private $bcc;
/**
* #var string
*
* #ORM\Column(name="subject", type="string", length=255, nullable=true)
*/
private $subject;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetime")
*/
private $date;
/**
* #var string
*
* #ORM\Column(name="content", type="text", nullable=true)
*/
private $content;
/**
* #var
*
* #ORM\OneToMany(targetEntity="MIP\CRMBundle\Entity\File", mappedBy="mail", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="file_id", referencedColumnName="id", nullable=true)
*/
protected $files;
/**
* #var ArrayCollection
*/
private $attached;
/**
* #var MailBox
* #ORM\ManyToOne(targetEntity="MailBox", inversedBy="mails")
* #ORM\JoinColumn(name="mailBox_id", referencedColumnName="id")
*/
private $mailBox;
/**
* #var LabelSticker
*
* #ORM\ManyToMany(targetEntity="\MIP\MailBundle\Entity\LabelSticker", mappedBy="mails")
*/
private $labels;
/**
* #var boolean
*/
private $readed;
/**
* #var boolean
*/
private $sent;
/**
* Constructor
* #param MailBox $mailbox
* #param boolean $readed
*/
public function __construct($mailbox, $readed)
{
$this->files = new ArrayCollection();
$this->date = new \DateTime('now');
$this->mailBox = $mailbox;
$this->readed = $readed;
}
Thanks for your help !

Symfony Circular Reference Exception with Doctrine tree extension

I have a Circular Reference Exception because of Doctrine Tree Extension when I'm tring to load my fixture with Alice fixture.
[Doctrine\Common\DataFixtures\Exception\CircularReferenceException]
Graph contains cyclic dependency. An example of this problem would be
the following: Class C has class B as its dependency. Then, class B
has class A has its dependency. Finally, class A has class C as
its dependency.
I have found the same problem here:
https://github.com/doctrine/data-fixtures/issues/232 but the solution does not work for me :( ...
I'm using this version of the doctrine fixtures.
"doctrine/data-fixtures": "1.2.1",
Here is my entity
namespace BaseBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Validator\Constraints as Assert;
/**
* BaseCategory
*
* #ORM\Entity()
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap({
* "article_category" = "AppBundle\Entity\ArticleCategory",
* "page_category" = "AppBundle\Entity\PageCategory",
* })
* #Gedmo\Tree(type="nested")
*/
abstract class BaseCategory
{
use \BaseBundle\Traits\SeoTrait;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
* #Assert\NotBlank()
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="slug", type="string", length=255, unique=true)
* #Gedmo\Slug(fields={"title"})
*/
private $slug;
/**
* #var string
*
* #ORM\Column(name="description", type="text")
*/
private $description;
/**
* #var \DateTime
*
* #ORM\Column(type="datetime")
* #Gedmo\Timestampable(on="create")
*/
private $createdAt;
/**
* #var \DateTime
*
* #ORM\Column(type="datetime")
* #Gedmo\Timestampable(on="update")
*/
private $updatedAt;
/**
* #Gedmo\TreeLeft
* #ORM\Column(type="integer")
*/
private $lft;
/**
* #Gedmo\TreeLevel
* #ORM\Column(type="integer")
*/
private $lvl;
/**
* #Gedmo\TreeRight
* #ORM\Column(type="integer")
*/
private $rgt;
/**
* #Gedmo\TreeRoot
* #ORM\ManyToOne(targetEntity="BaseCategory")
* #ORM\JoinColumn(referencedColumnName="id", onDelete="CASCADE")
*/
private $root;
/**
* #Gedmo\TreeParent
* #ORM\ManyToOne(targetEntity="BaseCategory", inversedBy="children")
* #ORM\JoinColumn(referencedColumnName="id", onDelete="CASCADE")
*/
private $parent;
/**
* #ORM\OneToMany(targetEntity="BaseCategory", mappedBy="parent")
* #ORM\OrderBy({"lft" = "ASC"})
*/
private $children;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
*
* #return BaseCategory
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set slug
*
* #param string $slug
*
* #return BaseCategory
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* Set description
*
* #param string $description
*
* #return BaseCategory
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* #return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* #return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
public function getRoot()
{
return $this->root;
}
public function setParent(BaseCategory $parent = null)
{
$this->parent = $parent;
}
public function getParent()
{
return $this->parent;
}
}
Is it normal? How can I fix that?

Runtime Notice: Accessing static property Proxies\__CG__\SimpleMediaBundle\Entity\Media::$lazyPropertiesDefaults as non static

I created a custom bundle called SimpleMedia. When I try to load a page that loads a company it gives me the Runtime Notice
Runtime Notice: Accessing static property Proxies__CG__\SimpleMediaBundle\Entity\Media::$lazyPropertiesDefaults as non static.
I know it has something to do with my one to one relation
(logoFile(Company Entity) -> id (Media Entity).
Anyone have any ideas? I am using Symfony 2.7
Controller
/**
* #Route("/{id}", name="api_company_show")
* #Method("GET")
* #param $id
* #return Response $response
*/
public function showAction($id) {
$company = $this->findCompanyById($id);
$response = $this->createApiResponse($company, 200);
return $response;
}
/**
* Find company by id. Throw exception if it does not.
* #param $id
* #return Company $company
*/
private function findCompanyById($id) {
$company = $this->getDoctrine()
->getRepository('AppBundle:Company')
->find($id);
if (!$company) {
throw $this->createNotFoundException(sprintf(
'No company found with id "%d"',
$id
));
}
return $company;
}
Company.php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\User;
use Symfony\Component\HttpFoundation\File\File;
use SimpleMediaBundle\Entity\Media;
/**
* Company
* #ORM\Table()
* #ORM\Entity(repositoryClass="AppBundle\Repository\CompanyRepository")
*/
class Company
{
/**
* #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)
*/
private $name;
/**
* #var string
* #ORM\Column(name="website", type="string", length=255, nullable=true)
*/
private $website;
/**
* #var string
* #ORM\Column(name="address_1", type="string", length=255, nullable=true)
*/
private $address1;
/**
* #var string
* #ORM\Column(name="address_2", type="string", length=255, nullable=true)
*/
private $address2;
/**
* #var string
* #ORM\Column(name="city", type="string", length=255, nullable=true)
*/
private $city;
/**
* #var string
* #ORM\Column(name="state", type="string", length=255, nullable=true)
*/
private $state;
/**
* #var string
* #ORM\Column(name="zipcode", type="string", length=50, nullable=true)
*/
private $zipcode;
/**
* #var string
* #ORM\Column(name="country", type="string", length=255, nullable=true)
*/
private $country;
/**
* #var string
* #ORM\Column(name="phone", type="string", length=50, nullable=true)
*/
private $phone;
/**
* #var string
* #ORM\Column(name="fax", type="string", length=50, nullable=true)
*/
private $fax;
/**
* #var integer
* #ORM\Column(name="years_in_business", type="integer", length=50, nullable=true)
*/
private $yearsInBusiness;
/**
* #var string
* #ORM\Column(name="number_of_employees", type="integer", length=50, nullable=true)
*/
private $numberOfEmployees;
/**
* #var integer
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\User")
*/
private $owners;
/**
* #ORM\OneToOne(targetEntity="SimpleMediaBundle\Entity\Media", cascade={"persist", "remove"}, orphanRemoval=true)
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="logo_file", referencedColumnName="id", nullable=true)
* })
*/
protected $logoFile;
/**
* #ORM\Column(type="datetime", name="updated", nullable=true)
* #var \DateTime $updated
*/
protected $updated;
public function __construct()
{
$this->owners = new ArrayCollection();
$this->logoFile = new ArrayCollection();
}
/**
* Get id
* #return integer
*/
public function getId()
{
return $this->id;
}
// Basic Getter and Setters
/**
* Set logo file id.
* #param Media $media
* #return $this
*/
public function setLogoFile(Media $media)
{
$this->logoFile = $media;
return $this;
}
/**
* Get Log File.
* #return File
*/
public function getLogoFile()
{
return $this->logoFile;
}
}
Media.php
namespace SimpleMediaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use SimpleMediaBundle\Entity\MediaInterface;
/**
* #ORM\Table()
* #ORM\Entity(repositoryClass="SimpleMediaBundle\Repository\MediaRepository")
*/
class Media implements MediaInterface
{
/**
* #var integer $id
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $name
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #var string $path
* #ORM\Column(name="path", type="string", length=500)
*/
private $path;
/**
* #var string $size
* #ORM\Column(name="size", type="integer", nullable=true)
*/
private $size;
/**
* #var string $createdAt
* #ORM\Column(name="created_at", type="datetime")
*/
private $createdAt;
/**
* #var string $createdAt
* #ORM\Column(name="updated_at", type="datetime")
*/
private $updatedAt;
/**
* #var string $contentType
* #ORM\Column(name="content_type", type="string", length=50, nullable=true)
*/
private $contentType;
/**
* #var string $type
* #ORM\Column(name="type", type="string", length=255)
*/
private $type;
public function __construct()
{
$this->createdAt = new \DateTime();
$this->updatedAt = new \DateTime();
}
/**
* Get id
* #return integer
*/
public function getId()
{
return $this->id;
}
// Basic Getter and Setters
/**
* Transform to string
* #return string
*/
public function __toString()
{
return (string) $this->getId();
}
}
Changing the fetch mode to EAGER fixed the issue for me.
/**
* #var Media
*
* #ORM\OneToOne(targetEntity="SimpleMediaBundle\Entity\Media", cascade={"persist", "remove"}, orphanRemoval=true, fetch="EAGER")
* #ORM\JoinColumn(name="logo_file", referencedColumnName="id", nullable=true)
*/
private $logoFile;
I think you have define the relationship wrong. I think should be:
/**
*
* #ORM\OneToOne(targetEntity="SimpleMediaBundle\Entity\Media", cascade={"persist", "remove"}, orphanRemoval=true)
* #ORM\JoinColumn(name="logo_file", referencedColumnName="id", nullable=true)
*/
protected $logoFile;
On the other hand, in the company constructor you dont need initialiser the $logoFile variable because is not a array it is just one value.

Doctrine2 cascade create

Here some context information: I'm building a Symfony2 application with Doctrine2 and FOSRestBundle.
My problem: I want to be able to create a parent with his children with just one JSON and one database access.
My JSON looks like this:
{
"name": "TEST_NAME",
"info": "TEST_INFO",
"cmts": [
{
"cmt": "CMT1",
"info": "INFO1"
},
{
"cmt": "CMT2",
"info": "INFO2"
},
{
"cmt": "CMT3",
"info": "INFO3"
}
]
}
Here is my TEST entity:
<?php
namespace App\Bundle\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Test
*
* #ORM\Table(name="Test")
* #ORM\Entity(repositoryClass="App\Bundle\DemoBundle\Entity\TestRepository")
*/
class Test
{
/**
* #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()
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="info", type="string", length=255, nullable=true)
*/
private $info;
/**
* #ORM\OneToMany(targetEntity="TestCmt", mappedBy="test", fetch="EAGER", orphanRemoval=true, cascade={"merge", "remove", "persist"})
*/
protected $cmts;
/**
* Constructor
*/
public function __construct()
{
$this->cmts = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add cmts
*
* #param \App\Bundle\DemoBundle\Entity\TestCmt $cmts
* #return Test
*/
public function addCmt(\App\Bundle\DemoBundle\Entity\TestCmt $cmts)
{
$this->cmts[] = $cmts;
return $this;
}
/**
* Remove cmts
*
* #param \App\Bundle\DemoBundle\Entity\TestCmt $cmts
*/
public function removeCmt(\App\Bundle\DemoBundle\Entity\TestCmt $cmts)
{
$this->cmts->removeElement($cmts);
}
/**
* Get cmts
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getCmts()
{
return $this->cmts;
}
// other getters/setters...
}
And my TESTCMT entity:
<?php
namespace App\Bundle\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* TestCmt
*
* #ORM\Table(name="TestCmt")
* #ORM\Entity(repositoryClass="App\Bundle\DemoBundle\Entity\TestCmtRepository")
*/
class TestCmt
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="cmt", type="string", length=255)
*/
private $cmt;
/**
* #var string
*
* #ORM\Column(name="info", type="string", length=255, nullable=true)
*/
private $info;
/**
* #var Test
*
* #ORM\ManyToOne(targetEntity="Test", inversedBy="cmts")
* #ORM\JoinColumn(name="test_id", referencedColumnName="id")
**/
private $test;
/**
* Set test
*
* #param \App\Bundle\DemoBundle\Entity\Test $test
* #return TestCmt
*/
public function setTest(\App\Bundle\DemoBundle\Entity\Test $test = null)
{
$this->test = $test;
return $this;
}
/**
* Get test
*
* #return \App\Bundle\DemoBundle\Entity\Test
*/
public function getTest()
{
return $this->test;
}
}
And finaly my postTestAction():
public function postTestAction(Request $request)
{
$entity = $this->deserialize($request, 'App\DemoBundle\Entity\Test');
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $entity;
}
When I send the JSON, TEST and TESTCMTs are created. Nevertheless, all "test_id" from the created TESTCMTs are "null"... And that's my problem!
EDIT: with SQL Server Profiler, I can see that Doctrine make that Transact SQL request:
INSERT INTO TESTCMT (test_id, cmt, info) VALUES (null, 'CMT', 'INFO')
I don't know why Doctrine can't send the test_id... TEST is created before TESTCMT, so "test_id" should be reachable for Doctrine to create the associate TESTCMTs.
Can someone helped me to fix it? :)
Remove #ORM\GeneratedValue(strategy="AUTO") and it won't let the DB generate a new id for the Entity

How to use Sluggable with a custom mapping type?

In a Symfony2 project, I created a custom mapping field in order to encrypt strings in the database as suggested in this StackOverflow question.
I want to slugify one of the database fields using the Gedmo\Sluggable Doctrine extension. But obviously I get the following error message because the "encrypted_string" is not an allowed type:
[Gedmo\Exception\InvalidMappingException]
Cannot use field - [username] for slug storage, type is not valid and must
be 'string' or 'text' in class - My\PrivateApplication\Bundle\UserBundle
\Entity\User
--EDIT--
This is my Entity:
<?php
namespace My\PrivateApplication\Bundle\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo,
Gedmo\Translatable\Translatable;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* My\PrivateApplication\Bundle\UserBundle\Entity\User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="UserRepository")
*/
class User implements AdvancedUserInterface, \Serializable {
/**
* #var int
*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(type="encrypted_string", length=255)
*/
private $surname;
/**
* #var string
*
* #ORM\Column(type="encrypted_string", length=255)
*/
private $name;
/**
* #var string
*
* #ORM\Column(type="encrypted_string", length=255, unique=true)
*/
private $username;
/**
* #var string
*
* #ORM\Column(type="string", length=255)
*/
private $password;
/**
* #var string
*
* #ORM\Column(type="encrypted_string", length=255)
*/
private $email;
/**
* #var string
*
* #ORM\Column(type="string", length=255, unique=true)
* #Gedmo\Slug(fields={"username"})
*/
private $slug;
/**
* #var string
*
* #ORM\Column(name="salt", type="string", length=40)
*/
private $salt;
/**
* Whether the account is active or not
*
* #var boolean
*
* #ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
/**
* Whether the account is locked or not
*
* #var boolean
*
* #ORM\Column(name="is_locked", type="boolean")
*/
private $isLocked;
/**
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime", nullable=true)
* #Gedmo\Timestampable(on="create")
*
*/
private $createdAt;
/**
* #var \DateTime
*
* #ORM\Column(name="updated_at", type="datetime", nullable=true)
* #Gedmo\Timestampable(on="update")
*/
private $updatedAt;
/**
* #var string
*
* #Gedmo\Locale
*/
private $locale;
/**
* Set the locale for the translatable behavior
*
* #param string $locale
*/
public function setTranslatableLocale($locale) {
$this->locale = $locale;
}
public function eraseCredentials()
{
}
public function getPassword()
{
return $this->password;
}
public function getRoles()
{
return array((string)$this->getRole());
}
public function getSalt()
{
return $this->salt;
}
public function getUsername()
{
return $this->username;
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return ($this->isLocked()==0)? false : true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return ($this->isActive==0) ? false : true;
}
/**
* Serialize the User object
* #see Serializable::serialize()
*/
public function serialize()
{
return serialize(array($this->id, $this->username, $this->password, $this->salt));
}
/**
* Unserialize the User object
* #see Serializable::unserialize()
*/
public function unserialize($serialized)
{
list($this->id, $this->username, $this->password, $this->salt) = unserialize($serialized);
}
//other accessor methods
}
The property $validTypes of the class Gedmo\Sluggable\Mapping\Driver\Annotation seems to define the valid types for the sluggable. How I can modify the SluggableListener to use my new custom type?
Thank you very much.

Resources