Create a createQueryBuilder with UniqueConstraint on 2 keys - doctrine

i'm trying to retrive data from several tables to make a json, but i'm stuck for the table having UniqueConstraint on 2 keys.
Here's my QueryBuilder sofar :
$qb = $this->_em->createQueryBuilder()
->select('partial s.{id, activity}, partial a.{id, title}, partial p.{id, evaluationType}')
->from('Innova\PathBundle\Entity\Step', 's')
->leftJoin('s.activity', 'a') //join on Activity entity
->leftJoin('a.parameters', 'p') // join on ActivityParameters entity
->andWhere('s.path = 2')
;
but i want to also join on Evaluation entity, which is :
/**
* #ORM\Table(
* name="claro_activity_evaluation",
* uniqueConstraints={
* #ORM\UniqueConstraint(
* name="user_activity_unique_evaluation",
* columns={"user_id", "activity_parameters_id"}
* )
* }
* )
*/
class Evaluation
{
/**
* #ORM\ManyToOne(targetEntity="Claroline\CoreBundle\Entity\User")
* #ORM\JoinColumn(onDelete="CASCADE", nullable=false)
*/
protected $user;
/**
* #ORM\ManyToOne(targetEntity="Claroline\CoreBundle\Entity\Activity\ActivityParameters")
* #ORM\JoinColumn(name="activity_parameters_id", onDelete="CASCADE", nullable=false)
*/
protected $activityParameters;
/**
* #ORM\Column(name="attempts_count", type="integer", nullable=true)
*/
protected $attemptsCount;
}
the User entity :
/**
* #ORM\Table(name="claro_user")
* #ORM\Entity(repositoryClass="Claroline\CoreBundle\Repository\UserRepository")
*/
class User
{
/**
* #var integer
*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="first_name", length=50)
* #Assert\NotBlank()
*/
protected $firstName;
}
The ActivityParameters entity
/**
* #ORM\Entity
* #ORM\Table(name="claro_activity_parameters")
*/
class ActivityParameters
{
/**
* #var integer
*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var \Claroline\CoreBundle\Entity\Resource\Activity
*
* #ORM\OneToOne(
* targetEntity="Claroline\CoreBundle\Entity\Resource\Activity",
* mappedBy="parameters"
* )
* #ORM\JoinColumn(name="activity_id", onDelete="CASCADE", nullable=true)
*/
protected $activity;
/**
* #var string
*
* #ORM\Column(name="evaluation_type", nullable=true)
*/
protected $evaluationType;
/**
* #return string
*/
public function getEvaluationType()
{
return $this->evaluationType;
}
}
the Activity entity
/**
* #ORM\Table(name="claro_activity")
*/
class Activity
{
/**
* #var string
* #ORM\Column(length=255, nullable=true)
*/
protected $title;
/**
* #ORM\OneToOne(
* targetEntity="Claroline\CoreBundle\Entity\Activity\ActivityParameters",
* inversedBy="activity",
* cascade={"persist"}
* )
* #ORM\JoinColumn(name="parameters_id", onDelete="cascade", nullable=true)
*/
protected $parameters;
/**
* #return string
*/
public function getTitle()
{
return $this->title;
}
}
I have no clue how to modify this querybuilder to retrieve also hte data from Evaluation entity. I want something like :
$qb = $this->_em->createQueryBuilder()
->select('partial s.{id, activity}, partial a.{id, title}, partial p.{id, evaluationType}, e')
->from('Innova\PathBundle\Entity\Step', 's')
->leftJoin('s.activity', 'a') //join on Activity entity
->leftJoin('a.parameters', 'p') // join on ActivityParameters entity
->andWhere('s.path = 2')
->leftJoin('?i dont know what?', 'e') // join on Evaluation entity
->andWhere('e.user = 3') //data for a specific user
;
Thank you for any help

I "seem" to have found a nearly working solution, reading this topic : i had to make a subquery :
$qb->select('e, partial p.{id, evaluationType}, partial a.{id, title}')
->from('Claroline\CoreBundle\Entity\Activity\Evaluation', 'e')
->leftJoin('e.activityParameters', 'p')
->leftJoin('p.activity', 'a')
->where(
$qb->expr()->in( //needs a subquery
'a.id',
$subq->select('a2.id')
->from('Innova\PathBundle\Entity\Step', 's')
->leftJoin(
's.activity',
'a2',
\Doctrine\ORM\Query\Expr\Join::WITH,
$subq->expr()->eq('s.path', '?1') //can't do a andWhere('s.path = :path'))
)
->getDQL() //needs a dql, not a querybuilder for the main query
)
)
->andWhere($qb->expr()->eq('e.user', '?2')) //can't do a andWhere('e.user = :user'))
->setParameter(1, $pid)
->setParameter(2, $uid)
;
I just would also like to retrieve the Step entity data (id, ...) in the query result. I can't add 's' to the main select : i have Error: 's' is used outside the scope of its declaration.

Related

ApiPlatform entity relation iri and schema

I cannot figure out how to reach this goal:
I want to have the object representation in a GET request with the related entity as json object too, while i want to send just the iri in a POST request of the parent object
/**
* #ORM\Entity(repositoryClass=CustomerRepository::class)
* #ApiResource
*/
class Customer
{
/**
* #var int|null
*
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #ApiProperty(
* identifier=false,
* description="ID univoco del cliente generato da un'operazione di POST"
* )
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="codice_cliente", type="string", length=20, unique=true)
* #ApiProperty(
* identifier=true,
* description="Codice identificativo del cliente.<br>Si tratta di un codice univoco che identifica il cliente all'interno dell'azienda di riferimento"
* )
*/
private $codiceCliente;
/**
* #var string|null
*
* #ORM\Column(name="ragione_sociale", type="string", length=50, nullable=true)
* #ApiProperty(description="Denominazione ufficiale del cliente")
*/
private $ragioneSociale;
/**
* #var string|null
*
* #ORM\Column(name="nome", type="string", length=50, nullable=true)
* #ApiProperty(description="Nome anagrafico del cliente")
*/
private $nome;
/**
* #var string|null
*
* #ORM\Column(name="cognome", type="string", length=50, nullable=true)
* #ApiProperty(description="Cognome anagrafico del cliente")
*/
private $cognome;
/**
* #var string|null
*
* #ORM\Column(name="codice_fiscale", type="string", length=16, nullable=true)
* #ApiProperty(description="Codice fiscale del cliente.<br>Può corrispondere a `partitaIva` in caso di azienda.")
*/
private $codiceFiscale;
/**
* #var string|null
*
* #ORM\Column(name="partita_iva", type="string", length=11, nullable=true)
* #ApiProperty(description="Partita Iva del cliente in caso di azienda.<br>È un valore numerico di 11 cifre.")
*/
private $partitaIva;
/**
* #var CustomerCategory
*
* #ORM\ManyToOne(targetEntity=CustomerCategory::class)
* #ORM\JoinColumn(name="categoria_id", referencedColumnName="codice", nullable=false)
*/
private $categoria;
/**
* #return int|null
*/
public function getId(): ?int
{
return $this->id;
}
/**
* #return string
*/
public function getCodiceCliente(): ?string
{
return $this->codiceCliente;
}
/**
* #param string $codiceCliente
*
* #return Customer
*/
public function setCodiceCliente(string $codiceCliente): Customer
{
$this->codiceCliente = $codiceCliente;
return $this;
}
/**
* #return string|null
*/
public function getRagioneSociale(): ?string
{
return $this->ragioneSociale;
}
/**
* #param string|null $ragioneSociale
*
* #return Customer
*/
public function setRagioneSociale(?string $ragioneSociale): Customer
{
$this->ragioneSociale = $ragioneSociale;
return $this;
}
/**
* #return string|null
*/
public function getNome(): ?string
{
return $this->nome;
}
/**
* #param string|null $nome
*
* #return Customer
*/
public function setNome(?string $nome): Customer
{
$this->nome = $nome;
return $this;
}
/**
* #return string|null
*/
public function getCognome(): ?string
{
return $this->cognome;
}
/**
* #param string|null $cognome
*
* #return Customer
*/
public function setCognome(?string $cognome): Customer
{
$this->cognome = $cognome;
return $this;
}
/**
* #return string|null
*/
public function getCodiceFiscale(): ?string
{
return $this->codiceFiscale;
}
/**
* #param string|null $codiceFiscale
*
* #return Customer
*/
public function setCodiceFiscale(?string $codiceFiscale): Customer
{
$this->codiceFiscale = $codiceFiscale;
return $this;
}
/**
* #return string|null
*/
public function getPartitaIva(): ?string
{
return $this->partitaIva;
}
/**
* #param string|null $partitaIva
*
* #return Customer
*/
public function setPartitaIva(?string $partitaIva): Customer
{
$this->partitaIva = $partitaIva;
return $this;
}
public function getCategoria(): ?CustomerCategory
{
return $this->categoria;
}
public function setCategoria(?CustomerCategory $categoria): self
{
$this->categoria = $categoria;
return $this;
}
}
/**
* #ORM\Entity(repositoryClass=CustomerCategoryRepository::class)
* #ApiResource()
*/
class CustomerCategory
{
/**
* #var string
*
* #ORM\Id
* #ORM\Column(type="string", length=10)
* #ApiProperty(identifier=true,
* description="Codice identificativo della categoria")
*/
private $codice;
/**
* #var string
*
* #ORM\Column(type="string", length=100, nullable=true)
* #ApiProperty(description="Descrizione del codice di identificazione")
*/
private $descrizione;
public function getCodice(): ?string
{
return $this->codice;
}
public function setCodice(string $codice): self
{
$this->codice = $codice;
return $this;
}
public function getDescrizione(): ?string
{
return $this->descrizione;
}
public function setDescrizione(?string $descrizione): self
{
$this->descrizione = $descrizione;
return $this;
}
}
So when i GET the Customer i want the $categoria property to be
{
codice: "10"
descrizione: "Test"
}
While when i POST/PUT/PATCH a Customer i want to refer to the CustomerCategory as the IRI of the ID as i don't have cascade persists in this case
{
"codiceCliente": "string",
"ragioneSociale": "string",
"nome": "string",
"cognome": "string",
"codiceFiscale": "string",
"partitaIva": "string",
"categoria": "/api/customer_categories/10"
}
I want also to have the correct representation on the OPEN API docs
You can get such results using a Serialization Group, except for the #id and #type being added to both Customer and to the $categoria property (API Platform automatically adds them).
First add the following to both your Entities:
use Symfony\Component\Serializer\Annotation\Groups;
To configure a Serialization Group only for the get operations of Customer:
/**
* #ORM\Entity(repositoryClass=CustomerRepository::class)
* #ApiResource(
* itemOperations={
* "get"={
* "normalization_context"={"groups"={"customer:get"}}
* },
* "patch",
* "put",
* "delete"
* },
* collectionOperations={
* "get"={
* "normalization_context"={"groups"={"customer:get"}}
* },
* "post"
* }
* )
*/
class Customer
//...
And then add #Groups({"customer:get"}) to the doc blocks of all props of Customer except $id, including $categoria. I only give one example here:
/**
* #var string|null
*
* #ORM\Column(name="ragione_sociale", type="string", length=50, nullable=true)
* #ApiProperty(description="Denominazione ufficiale del cliente")
* #Groups({"customer:get"})
*/
private $ragioneSociale;
Also add #Groups({"customer:get"}) to the doc blocks of $codice and $descrizione of CustomerCategory.
This should do the trick and leave the post, put and patch operations unchanged (expecting and returning just the iri of $categoria). It should automatically give a correct representation on the OPEN API docs.
Tip: The readme of branch chapter4-api of my tutorial also contains instructions for adding Serialization Groups two Entities related like yours, and the resulting code is in branch chapter5-api.

DQL join two joined tables from different tables

I know the title isn't very clear, but I will try to better explain my problem here.
I have 3 Doctrine entities : A, B and C
class A { class B { class C {
$id; $id; $id;
ManyToMany ManyToMany }
$C; $C;
} }
I'm trying to know if an object A and an object B have at least one same C.
The many to many relations gives me table like :
table AC { table BC {
A_id; B_id;
C_id; C_id;
} }
I know that I can't use these tables in DQL but what I want to do can be done in SQL. It would give :
SELECT COUNT(A.id) FROM AC INNER JOIN BC
ON AC.C_id = BC.C_id
WHERE BC.B_id=1217 AND AC.A_id=185
You will need to make the many to many accosiation bidirectional, so entities will look like this:
<?php
namespace App\Model;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class A
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
* #var integer
*/
private $id;
/**
* #var ArrayCollection|C[]
* #ORM\ManyToMany(targetEntity="C", inversedBy="as")
*/
private $cs;
}
/**
* #ORM\Entity
*/
class B
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
* #var integer
*/
private $id;
/**
* #var ArrayCollection|C[]
* #ORM\ManyToMany(targetEntity="C", inversedBy="bs")
*/
private $cs;
}
/**
* #ORM\Entity
*/
class C
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
* #var integer
*/
private $id;
/**
* #var ArrayCollection|A[]
* #ORM\ManyToMany(targetEntity="A", mappedBy="cs")
*/
private $as;
/**
* #var ArrayCollection|A[]
* #ORM\ManyToMany(targetEntity="B", mappedBy="cs")
*/
private $bs;
}
And then you can query the C class with conditional join on A and B entities, by this DQL query:
$query = $this->entityManager->createQuery("SELECT count(c.id) FROM C::class c INNER JOIN c.as a WITH a.id = :a_id INNER JOIN c.bs b WITH b.id = :b_id")
->setParameter('a_id', 185)
->setParameter('b_id', 1217);
$result = $query->getSingleScalarResult();

Symfony3 Edit Entity : Error Missing value for primary key

I try to create a tree structure for a catalog of products.
A catalog can have multiple levels and levels can contain multiple products.
I manage to save my structure in database but when I want to edit it, I have this error :
Error : Missing value for primary key catalogCode on AppBundle\Entity\CatalogLevel
at OutOfBoundsException ::missingPrimaryKeyValue ('AppBundle\Entity\CatalogLevel', 'catalogCode')
in vendor\doctrine\common\lib\Doctrine\Common\Proxy\AbstractProxyFactory.php at line 125
when I do this in my CatalogController :
$form = $this->createForm(CatalogTreeType::class, $catalog);
But, just before that line, I verify if I get my levels correctly and it's looking like that's the case :
// Create an ArrayCollection of the current levels
$originalLevels = new ArrayCollection();
foreach ($catalog->getLevels() as $level) {
var_dump($level->getCatalogCode());
$originalLevels->add($level);
}
// returns
AppBundle\Controller\CatalogController.php:337:string 'TT-FTEST' (length=8)
AppBundle\Controller\CatalogController.php:337:string 'TT-FTEST' (length=8)
CatalogLevel entity has a composite key : levelId + catalogCode.
Considering the primary key catalogCode isn't empty, I don't understand this error...
Catalog Entity
/**
* #ORM\Table(name="catalogue")
* #ORM\Entity(repositoryClass="AppBundle\Entity\CatalogRepository")
* #UniqueEntity(fields="code", message="Catalog code already exists")
*/
class Catalog
{
/**
* #ORM\Column(name="Catalogue_Code", type="string", length=15)
* #ORM\Id
* #Assert\NotBlank()
* #Assert\Length(max=15, maxMessage="The code is too long ({{ limit }} characters max)")
*/
private $code;
/**
* #ORM\OneToMany(targetEntity="CatalogLevel", mappedBy="catalog", cascade={"persist", "remove"})
* #Assert\Valid
*/
private $levels;
/**
* Constructor
*/
public function __construct()
{
$this->levels = new ArrayCollection();
}
/**
* Get levels
*
* #return ArrayCollection
*/
public function getLevels()
{
return $this->levels;
}
/**
* Add level
*
* #param \AppBundle\Entity\CatalogLevel $level
*
* #return Catalog
*/
public function addLevel(\AppBundle\Entity\CatalogLevel $level)
{
$level->setCatalogCode($this->getCode());
$level->setCatalog($this);
if (!$this->getLevels()->contains($level)) {
$this->levels->add($level);
}
return $this;
}
/**
* Remove level
*
* #param \AppBundle\Entity\CatalogLevel $level
*/
public function removeLevel(\AppBundle\Entity\CatalogLevel $level)
{
$this->levels->removeElement($level);
}
}
CatalogLevel Entity
/**
* #ORM\Table(name="catalogue_niveau")
* #ORM\Entity(repositoryClass="AppBundle\Entity\CatalogLevelRepository")
*/
class CatalogLevel
{
/**
* #ORM\Column(name="Niveau_ID", type="string", length=15)
* #ORM\Id
*/
private $id;
/**
* #ORM\Column(name="Catalogue_Code", type="string", length=15)
* #ORM\Id
*/
private $catalogCode;
/**
* #ORM\ManyToOne(targetEntity="Catalog", inversedBy="levels")
* #ORM\JoinColumn(name="Catalogue_Code", referencedColumnName="Catalogue_Code")
*/
private $catalog;
/**
* Set id
*
* #param string $id
*
* #return CatalogLevel
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Get id
*
* #return string
*/
public function getId()
{
return $this->id;
}
/**
* Set catalogCode
*
* #param string $catalogCode
*
* #return CatalogLevel
*/
public function setCatalogCode($catalogCode)
{
$this->catalogCode = $catalogCode;
return $this;
}
/**
* Get catalogCode
*
* #return string
*/
public function getCatalogCode()
{
return $this->catalogCode;
}
}
I would like to remind you that this error occured on the editAction (it works very well on the addAction) when I display the pre-filled form.
Thanks for your help !
I think that is because you haven't autoincrement id in entity CatalogLevel. Try add to id this code:
#ORM\GeneratedValue(strategy="AUTO")
You have some problems in the way you've created you Entities. You should use auto generate strategy. Also the "#ORM\Id" annotation is the unique identifier.
Also, your "JoinColumn" is incorrect. You need to refer back to the "Catalog" Entity, and it's id (identifier). There is no need for 2 "#ORM\Id" entries in the class CatalogLevel.
So make these changes:
/**
* #ORM\Table(name="catalog")
* #ORM\Entity(repositoryClass="AppBundle\Entity\CatalogRepository")
*/
class Catalog
{
/**
* #ORM\Column(name="cat_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $cat_id;
/**
* #ORM\OneToMany(targetEntity="CatalogLevel", mappedBy="catalog", cascade={"persist", "remove"})
* #Assert\Valid
*/
private $levels;
...
/**
* #ORM\Table(name="catalog_level")
* #ORM\Entity(repositoryClass="AppBundle\Entity\CatalogLevelRepository")
*/
class CatalogLevel
{
/**
* #ORM\Column(name="cat_level_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $cat_level_id;
/**
* #ORM\ManyToOne(targetEntity="Catalog", inversedBy="levels")
* #ORM\JoinColumn(name="local_cat_id", referencedColumnName="cat_id")
*/
private $catalog;
...

Vich upload bundle remove image

Hi guys i have implemented vichuploadbundle to upload images but i want in the admin the user to remove the image.
<?php
namespace George\PageBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use George\UserBundle\Entity\User;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* Page
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="George\PageBundle\Entity\PageRepository")
* #Vich\Uploadable
*/
class Page
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="text")
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="content", type="text")
*/
private $content;
/**
* #var boolean
*
* #ORM\Column(name="visible", type="boolean")
*/
private $visible;
/**
* #var \DateTime
*
* #ORM\Column(name="created", type="datetime")
*/
private $created;
/**
* #var \DateTime
*
* #ORM\Column(name="modefied", type="datetime")
*/
private $modefied;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=255)
*/
private $description;
/**
* #var string
*
* #ORM\Column(name="keywords", type="string", length=255)
*/
private $keywords;
/**
* #ORM\ManyToOne(targetEntity="George\UserBundle\Entity\User", inversedBy="pages")
* #ORM\JoinColumn(onDelete="CASCADE")
*/
private $owner;
//#ORM\Column(length=128, unique=true)
/**
* #Gedmo\Slug(fields={"title"})
* #ORM\Column(length=128, unique=true)
*/
private $slug;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
*
* #return Page
*/
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 Page
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get content
*
* #return string
*/
public function getContent()
{
return $this->content;
}
/**
* Set visible
*
* #param boolean $visible
*
* #return Page
*/
public function setVisible($visible)
{
$this->visible = $visible;
return $this;
}
/**
* Get visible
*
* #return boolean
*/
public function getVisible()
{
return $this->visible;
}
/**
* Set created
*
* #param \DateTime $created
*
* #return Page
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set modefied
*
* #param \DateTime $modefied
*
* #return Page
*/
public function setModefied($modefied)
{
$this->modefied = $modefied;
return $this;
}
/**
* Get modefied
*
* #return \DateTime
*/
public function getModefied()
{
return $this->modefied;
}
/**
* Set description
*
* #param string $description
*
* #return Page
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set keywords
*
* #param string $keywords
*
* #return Page
*/
public function setKeywords($keywords)
{
$this->keywords = $keywords;
return $this;
}
/**
* Get keywords
*
* #return string
*/
public function getKeywords()
{
return $this->keywords;
}
/**
* #return mixed
*/
public function getOwner()
{
return $this->owner;
}
/**
* #param mixed $owner
*/
public function setOwner(User $owner)
{
$this->owner = $owner;
}
public function getSlug()
{
return $this->slug;
}
// ..... other fields
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="product_image", fileNameProperty="imageName")
*
* #var File
*/
private $imageFile;
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
private $imageName;
/**
* #ORM\Column(type="datetime")
*
* #var \DateTime
*/
private $updatedAt;
/**
* 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;
}
/**
* #param string $imageName
*/
public function setImageName($imageName)
{
$this->imageName = $imageName;
}
/**
* #return string
*/
public function getImageName()
{
return $this->imageName;
}
}
Can you advice me what is the best solution to this. I think it will be best if i have a method remove image and in the method try to use bundles build in function for removal the image (which i don't find anywhere) and update it in the database. In the front end this can be don trough ajax or on submit... Is there a build in function for the removal of file in the vichuploadbundle?
I have found how to remove the image. The bundle provides a custom form type in order to ease the upload, deletion and download of images.
When you build the form you specifies the widget:
public function buildForm(FormBuilderInterface $builder, array $options)
{
// ...
$builder->add('image', 'vich_image', array(
'required' => false,
'allow_delete' => true, // not mandatory, default is true
'download_link' => true, // not mandatory, default is true
));
}
This add a twig template for deleting the img :)

#AssociationOverride and #AttributeOverride in new Doctrine 2.3

As per title, what's the purpose of the new annotation #AssociationOverride and #AttributeOverride?
The only thing I can find on Doctrine website is:
#AssociationOverride and #AttributeOverride (useful for Trait and
MappedSuperclass)
By looking at the code in the commit, we can see that it is used to override a field mapping already defined in a mapped superclass / trait.
The tests included in the commit demonstrate this behaviour:
Mapped superclass
/**
* #MappedSuperclass
*/
class User
{
/**
* #Id
* #GeneratedValue
* #Column(type="integer", name="user_id", length=150)
*/
protected $id;
/**
* #Column(name="user_name", nullable=true, unique=false, length=250)
*/
protected $name;
/**
* #var ArrayCollection
*
* #ManyToMany(targetEntity="Group", inversedBy="users", cascade={"persist", "merge", "detach"})
* #JoinTable(name="users_groups",
* joinColumns={#JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
protected $groups;
/**
* #var Address
*
* #ManyToOne(targetEntity="Address", cascade={"persist", "merge"})
* #JoinColumn(name="address_id", referencedColumnName="id")
*/
protected $address;
...
}
Subclass using #AssociationOverride
/*
* #Entity
* #AssociationOverrides({
* #AssociationOverride(name="groups",
* joinTable=#JoinTable(
* name="users_admingroups",
* joinColumns=#JoinColumn(name="adminuser_id"),
* inverseJoinColumns=#JoinColumn(name="admingroup_id")
* )
* ),
* #AssociationOverride(name="address",
* joinColumns=#JoinColumn(
* name="adminaddress_id", referencedColumnName="id"
* )
* )
* })
*/
class Admin extends User
{
...
}
Subclass using #AttributeOverride
/**
* #Entity
* #AttributeOverrides({
* #AttributeOverride(name="id",
* column=#Column(
* name = "guest_id",
* type = "integer",
* length = 140
* )
* ),
* #AttributeOverride(name="name",
* column=#Column(
* name = "guest_name",
* nullable = false,
* unique = true,
* length = 240
* )
* )
* })
*/
class Guest extends User
{
...
}

Resources