I'm new on Symfony 6 and i've got some questions about this framework.
Recently i got this error but i don't understand why. I created all databases from the command line.
My error is : Case mismatch between loaded and declared class names: "App\Entity\tag" vs "App\Entity\Tag".
In my database all tables are written with lowercase syntaxe.
everything worked between I insert relation with all table.
i tried to insert this code in my entity to use the correct syntaxe but it doesn't work.
Entity\Tag.php
#[ORM\Table(name: 'tag')]
Some people speak about this parameter inside my database (MYSQL) but i don't know if this got an impact :
lower_case_table_names = (0 1 2)
Do you have an idea ?
This is my entity tag
<?php
namespace App\Entity;
use App\Repository\TagRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: TagRepository::class)]
class Tag
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $nomtag = null;
#[ORM\ManyToOne(inversedBy: 'idcatetag')]
#[ORM\JoinColumn(nullable: false)]
private ?catetag $idcatetag = null;
#[ORM\ManyToMany(targetEntity: Mission::class, mappedBy: 'idtagmissionassign')]
private Collection $missions;
#[ORM\ManyToMany(targetEntity: Service::class, mappedBy: 'idtagserviceassign')]
private Collection $services;
public function __construct()
{
$this->missions = new ArrayCollection();
$this->services = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getNomtag(): ?string
{
return $this->nomtag;
}
public function setNomtag(string $nomtag): self
{
$this->nomtag = $nomtag;
return $this;
}
public function getIdcatetag(): ?catetag
{
return $this->idcatetag;
}
public function setIdcatetag(?catetag $idcatetag): self
{
$this->idcatetag = $idcatetag;
return $this;
}
/**
* #return Collection<int, Mission>
*/
public function getMissions(): Collection
{
return $this->missions;
}
public function addMission(Mission $mission): self
{
if (!$this->missions->contains($mission)) {
$this->missions->add($mission);
$mission->addIdtagmissionassign($this);
}
return $this;
}
public function removeMission(Mission $mission): self
{
if ($this->missions->removeElement($mission)) {
$mission->removeIdtagmissionassign($this);
}
return $this;
}
/**
* #return Collection<int, Service>
*/
public function getServices(): Collection
{
return $this->services;
}
public function addService(Service $service): self
{
if (!$this->services->contains($service)) {
$this->services->add($service);
$service->addIdtagserviceassign($this);
}
return $this;
}
public function removeService(Service $service): self
{
if ($this->services->removeElement($service)) {
$service->removeIdtagserviceassign($this);
}
return $this;
}
}
This is my repo file :
<?php
namespace App\Repository;
use App\Entity\Tag;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* #extends ServiceEntityRepository<Tag>
*
* #method Tag|null find($id, $lockMode = null, $lockVersion = null)
* #method Tag|null findOneBy(array $criteria, array $orderBy = null)
* #method Tag[] findAll()
* #method Tag[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class TagRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Tag::class);
}
public function save(Tag $entity, bool $flush = false): void
{
$this->getEntityManager()->persist($entity);
if ($flush) {
$this->getEntityManager()->flush();
}
}
public function remove(Tag $entity, bool $flush = false): void
{
$this->getEntityManager()->remove($entity);
if ($flush) {
$this->getEntityManager()->flush();
}
}
// /**
// * #return Tag[] Returns an array of Tag objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('t')
// ->andWhere('t.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('t.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?Tag
// {
// return $this->createQueryBuilder('t')
// ->andWhere('t.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
check file name , it should be Tag.php with T uppercase, symfony create table automatically in lowercase. If everything is ok try to delete you're file and rewrite it properly with make:entity or php bin/console doctrine:schema:update --force after entity's modification
Related
i have a entity called "AreasProfesionales"
use Doctrine\ORM\Mapping as ORM;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\InverseJoinColumn;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use App\Repository\AreasProfesionalesRepository;
use Doctrine\Common\Collections\ArrayCollection;
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[ORM\Entity(repositoryClass: AreasProfesionalesRepository::class)]
#[UniqueEntity(fields: ['Codigo'], message: 'Ya existe un area profesional registrada con ese mismo código')]
#[ApiFilter(SearchFilter::class, properties: ['Denominacion' => 'partial', 'Codigo' => 'partial', 'familiasProfesionales'=> 'exact'])]
#[ApiFilter(OrderFilter::class, properties: ['id'], arguments: ['orderParameterName' => 'order'])]
#[ApiResource(paginationEnabled: false,formats: ['json' => ['application/json']],
normalizationContext: ['groups' => ['read']],
denormalizationContext: ['groups' => ['write']])]
class AreasProfesionales
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
#[Groups(['read','write'])]
#[ApiProperty(writable:true)]
private ?int $id = null;
#[ORM\Column(length: 255)]
#[Groups(['read','write'])]
private ?string $Denominacion = null;
#[ORM\Column(length: 20, unique:true)]
#[Groups(['read', 'write'])]
private ?string $Codigo = null;
#[ORM\ManyToOne(inversedBy: 'Familiasprofesionales_areasprofesionales')]
#[Groups(['read','write'])]
#[InverseJoinColumn(name: "familias_profesionales_id", referencedColumnName: "id")]
#[ApiProperty(readableLink: true, writableLink: true)]
private ?FamiliasProfesionales $familiasProfesionales = null;
#[ORM\OneToMany(mappedBy: 'areasProfesionales', targetEntity: CertificadosProfesionalidad::class)]
private Collection $Areasprofesionales_certificadosprofesionalidad;
#[ORM\OneToMany(mappedBy: 'areasProfesionales', targetEntity: AreasProfesionalesDocentes::class)]
private Collection $Areasprofesionales_areasprofesionalesdocentes;
#[ORM\OneToMany(mappedBy: 'areasProfesionales', targetEntity: AreasProfesionalesItinerariosFormativos::class)]
private Collection $Areasprofesionales_areasprofesionalesitinerariosformativos;
public function __construct()
{
$this->Areasprofesionales_certificadosprofesionalidad = new ArrayCollection();
$this->Areasprofesionales_areasprofesionalesdocentes = new ArrayCollection();
$this->Areasprofesionales_areasprofesionalesitinerariosformativos = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getDenominacion(): ?string
{
return $this->Denominacion;
}
public function setDenominacion(string $Denominacion): self
{
$this->Denominacion = $Denominacion;
return $this;
}
public function getCodigo(): ?string
{
return $this->Codigo;
}
public function setCodigo(string $Codigo): self
{
$this->Codigo = $Codigo;
return $this;
}
public function getFamiliasProfesionales(): ?FamiliasProfesionales
{
return $this->familiasProfesionales;
}
public function setFamiliasProfesionales(?FamiliasProfesionales $familiasProfesionales): self
{
$this->familiasProfesionales = $familiasProfesionales;
return $this;
}
/**
* #return Collection<int, CertificadosProfesionalidad>
*/
/*public function getAreasprofesionalesCertificadosprofesionalidad(): Collection
{
return $this->Areasprofesionales_certificadosprofesionalidad;
}
public function addAreasprofesionalesCertificadosprofesionalidad(CertificadosProfesionalidad $areasprofesionalesCertificadosprofesionalidad): self
{
if (!$this->Areasprofesionales_certificadosprofesionalidad->contains($areasprofesionalesCertificadosprofesionalidad)) {
$this->Areasprofesionales_certificadosprofesionalidad->add($areasprofesionalesCertificadosprofesionalidad);
$areasprofesionalesCertificadosprofesionalidad->setAreasProfesionales($this);
}
return $this;
}
public function removeAreasprofesionalesCertificadosprofesionalidad(CertificadosProfesionalidad $areasprofesionalesCertificadosprofesionalidad): self
{
if ($this->Areasprofesionales_certificadosprofesionalidad->removeElement($areasprofesionalesCertificadosprofesionalidad)) {
// set the owning side to null (unless already changed)
if ($areasprofesionalesCertificadosprofesionalidad->getAreasProfesionales() === $this) {
$areasprofesionalesCertificadosprofesionalidad->setAreasProfesionales(null);
}
}
return $this;
}*/
/**
* #return Collection<int, AreasProfesionalesDocentes>
*/
/public function getAreasprofesionalesAreasprofesionalesdocentes(): Collection
{
return $this->Areasprofesionales_areasprofesionalesdocentes;
}
public function addAreasprofesionalesAreasprofesionalesdocente(AreasProfesionalesDocentes $areasprofesionalesAreasprofesionalesdocente): self
{
if (!$this->Areasprofesionales_areasprofesionalesdocentes->contains($areasprofesionalesAreasprofesionalesdocente)) {
$this->Areasprofesionales_areasprofesionalesdocentes->add($areasprofesionalesAreasprofesionalesdocente);
$areasprofesionalesAreasprofesionalesdocente->setAreasProfesionales($this);
}
return $this;
}
public function removeAreasprofesionalesAreasprofesionalesdocente(AreasProfesionalesDocentes $areasprofesionalesAreasprofesionalesdocente): self
{
if ($this->Areasprofesionales_areasprofesionalesdocentes->removeElement($areasprofesionalesAreasprofesionalesdocente)) {
// set the owning side to null (unless already changed)
if ($areasprofesionalesAreasprofesionalesdocente->getAreasProfesionales() === $this) {
$areasprofesionalesAreasprofesionalesdocente->setAreasProfesionales(null);
}
}
return $this;
}*/
/**
* #return Collection<int, AreasProfesionalesItinerariosFormativos>
*/
public function getAreasprofesionalesAreasprofesionalesitinerariosformativos(): Collection
{
return $this->Areasprofesionales_areasprofesionalesitinerariosformativos;
}
public function addAreasprofesionalesAreasprofesionalesitinerariosformativo(AreasProfesionalesItinerariosFormativos $areasprofesionalesAreasprofesionalesitinerariosformativo): self
{
if (!$this->Areasprofesionales_areasprofesionalesitinerariosformativos->contains($areasprofesionalesAreasprofesionalesitinerariosformativo)) {
$this->Areasprofesionales_areasprofesionalesitinerariosformativos->add($areasprofesionalesAreasprofesionalesitinerariosformativo);
$areasprofesionalesAreasprofesionalesitinerariosformativo->setAreasProfesionales($this);
}
return $this;
}
public function removeAreasprofesionalesAreasprofesionalesitinerariosformativo(AreasProfesionalesItinerariosFormativos $areasprofesionalesAreasprofesionalesitinerariosformativo): self
{
if ($this->Areasprofesionales_areasprofesionalesitinerariosformativos->removeElement($areasprofesionalesAreasprofesionalesitinerariosformativo)) {
// set the owning side to null (unless already changed)
if ($areasprofesionalesAreasprofesionalesitinerariosformativo->getAreasProfesionales() === $this) {
$areasprofesionalesAreasprofesionalesitinerariosformativo->setAreasProfesionales(null);
}
}
return $this;
}
public function __toString()
{
return $this->id;
}
I have another entity called "FamiliasProfesionales"
use Doctrine\ORM\Mapping as ORM;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use Doctrine\Common\Collections\Collection;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use Doctrine\Common\Collections\ArrayCollection;
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use App\Repository\FamiliasProfesionalesRepository;
use Symfony\Component\Serializer\Annotation\Groups;
#[ORM\Entity(repositoryClass: FamiliasProfesionalesRepository::class)]
#[ApiFilter(SearchFilter::class, properties: ['Denominacion' => 'partial'])]
#[ApiFilter(OrderFilter::class, properties: ['id', 'Denominacion'], arguments: ['orderParameterName' => 'order'])]
#[ApiResource(paginationEnabled: false,formats: ['json' => ['application/json']],
normalizationContext: ['groups' => ['read']],
denormalizationContext: ['groups' => ['write']])]
class FamiliasProfesionales
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
#[Groups(['read','write'])]
#[ApiProperty(writable:true)]
private ?int $id = null;
#[ORM\Column(length: 255)]
#[Groups(['read','write'])]
private ?string $Denominacion = null;
#[ORM\OneToMany(mappedBy: 'familiasProfesionales', targetEntity: AreasProfesionales::class)]
#[ORM\JoinColumn()]
private Collection $Familiasprofesionales_areasprofesionales;
public function __construct()
{
$this->Familiasprofesionales_areasprofesionales = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getDenominacion(): ?string
{
return $this->Denominacion;
}
public function setDenominacion(string $Denominacion): self
{
$this->Denominacion = $Denominacion;
return $this;
}
/**
* #return Collection<int, AreasProfesionales>
*/
public function getFamiliasprofesionalesAreasprofesionales(): Collection
{
return $this->Familiasprofesionales_areasprofesionales;
}
public function addFamiliasprofesionalesAreasprofesionale(AreasProfesionales $familiasprofesionalesAreasprofesionale): self
{
if (!$this->Familiasprofesionales_areasprofesionales->contains($familiasprofesionalesAreasprofesionale)) {
$this->Familiasprofesionales_areasprofesionales->add($familiasprofesionalesAreasprofesionale);
$familiasprofesionalesAreasprofesionale->setFamiliasProfesionales($this);
}
return $this;
}
public function removeFamiliasprofesionalesAreasprofesionale(AreasProfesionales $familiasprofesionalesAreasprofesionale): self
{
if ($this->Familiasprofesionales_areasprofesionales->removeElement($familiasprofesionalesAreasprofesionale)) {
// set the owning side to null (unless already changed)
if ($familiasprofesionalesAreasprofesionale->getFamiliasProfesionales() === $this) {
$familiasprofesionalesAreasprofesionale->setFamiliasProfesionales(null);
}
}
return $this;
}
public function __toString()
{
return $this->id;
}
}
I´m using API PLATFORM in my proyect to show all the operations and services.
Is there a way to get only a single field from the Collection? I want the entity "AreasProfesionales" to only appear, for example, the id from "FamiliasProfesionales"
if I need to create a new professional area in the POST method, I only have to enter the id of the professional family to which it belongs and not have to enter all the other data, however, it returns all its fields.Thank you in advance.
I have been trying using the read and write methods of API Platform, but I don't get the result I want, I think the problem is that Api Platform works with IRI and not with id (but i need work with this one).
Yes you can :
<?php
// api/src/Entity/Book.php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;
#[ApiResource(normalizationContext: ['groups' => ['book']])]
class Book
{
#[Groups('book')]
public $name;
#[Groups('book')]
public $author;
// ...
}
you can follow this documentation : https://api-platform.com/docs/core/serialization/
Regards,
I have a small simple symfony 6.1.4 application and wanted to write a API for a few Entities, but when i fetch the data from the database (mysql) i get something what looks like a class description.
$test = $this->audienceRepository->createQueryBuilder('s')->getQuery()->getResult();
var_dump($test);
Entity
<?php
namespace App\Entity;
use App\Repository\AudienceRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: AudienceRepository::class)]
class Audience
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $name = null;
#[ORM\Column]
private ?bool $is_department = null;
#[ORM\Column]
private ?bool $is_company = null;
#[ORM\OneToMany(mappedBy: 'department', targetEntity: User::class)]
private Collection $users;
#[ORM\ManyToMany(targetEntity: Seminar::class, mappedBy: 'audience')]
private Collection $seminars;
public function __construct()
{
$this->users = new ArrayCollection();
$this->seminars = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function isIsDepartment(): ?bool
{
return $this->is_department;
}
public function setIsDepartment(bool $is_department): self
{
$this->is_department = $is_department;
return $this;
}
public function isIsCompany(): ?bool
{
return $this->is_company;
}
public function setIsCompany(bool $is_company): self
{
$this->is_company = $is_company;
return $this;
}
/**
* #return Collection<int, User>
*/
public function getUsers(): Collection
{
return $this->users;
}
public function addUser(User $user): self
{
if (!$this->users->contains($user)) {
$this->users->add($user);
$user->setDepartment($this);
}
return $this;
}
public function removeUser(User $user): self
{
if ($this->users->removeElement($user)) {
// set the owning side to null (unless already changed)
if ($user->getDepartment() === $this) {
$user->setDepartment(null);
}
}
return $this;
}
/**
* #return Collection<int, Seminar>
*/
public function getSeminars(): Collection
{
return $this->seminars;
}
public function addSeminar(Seminar $seminar): self
{
if (!$this->seminars->contains($seminar)) {
$this->seminars->add($seminar);
$seminar->addAudience($this);
}
return $this;
}
public function removeSeminar(Seminar $seminar): self
{
if ($this->seminars->removeElement($seminar)) {
$seminar->removeAudience($this);
}
return $this;
}
}
Repository
namespace App\Repository;
use App\Entity\Audience;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* #extends ServiceEntityRepository<Audience>
*
* #method Audience|null find($id, $lockMode = null, $lockVersion = null)
* #method Audience|null findOneBy(array $criteria, array $orderBy = null)
* #method Audience[] findAll()
* #method Audience[] findBy(array $criteria, array $orderBy = null, $limit =null, $offset = null)
*/
class AudienceRepository extends ServiceEntityRepository {
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Audience::class);
}
public function add(Audience $entity, bool $flush = false): void
{
$this->getEntityManager()->persist($entity);
if ($flush) {
$this->getEntityManager()->flush();
}
}
public function remove(Audience $entity, bool $flush = false): void
{
$this->getEntityManager()->remove($entity);
if ($flush) {
$this->getEntityManager()->flush();
}
}
result of var_dumb
I couldnt find why doctrine is behaving this way. Does someone know why and how to prevent that?
Everything is correct as the doctrine returns to you Objects of your ENTITY filled with data from the DB
You get Each row as a separate class and can use it as follows
<?php
foreach($results as $audience) {
$audience->getId();
}
Doctrine return to you list object with set data in Entity: Example
<?php
class Audience
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = 12;
#[ORM\Column(length: 255)]
private ?string $name = "You name from DB";
#[ORM\Column]
private ?bool $is_department = true;
#[ORM\Column]
private ?bool $is_company = true;
#[ORM\OneToMany(mappedBy: 'department', targetEntity: User::class)]
private Collection $users = new Collection(<With Users objects>);;
#[ORM\ManyToMany(targetEntity: Seminar::class, mappedBy: 'audience')]
private Collection $seminars = new Collection(<With Seminars objects>);
i have a problem with my code and maybe with with my relations into my database. I will expose you my code next. I want to delete only a deliver, but it delete me the user too. If you can help me because I don't uderstand why it does this. Thank you
My database view
Deliverer.php
<?php
namespace App\Entity;
use App\Repository\DelivererRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: DelivererRepository::class)]
class Deliverer
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(type: Types::DECIMAL, precision: 3, scale: 1, nullable: true)]
private ?string $rate = null;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $info = null;
#[ORM\OneToMany(mappedBy: 'deliverer', targetEntity: Order::class)]
private Collection $orders;
#[ORM\ManyToOne(inversedBy: 'deliverers')]
private ?Vehicle $vehicle = null;
#[ORM\Column]
private ?int $nbRate = 0;
#[ORM\OneToOne(inversedBy: 'deliverer', cascade: ['persist', 'remove'])]
private ?User $user = null;
public function __construct()
{
$this->orders = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getRate(): ?string
{
return $this->rate;
}
public function setRate(?string $rate): self
{
$this->rate = $rate;
return $this;
}
public function getInfo(): ?string
{
return $this->info;
}
public function setInfo(?string $info): self
{
$this->info = $info;
return $this;
}
/**
* #return Collection<int, Order>
*/
public function getOrders(): Collection
{
return $this->orders;
}
public function addOrder(Order $order): self
{
if (!$this->orders->contains($order)) {
$this->orders->add($order);
$order->setDeliverer($this);
}
return $this;
}
public function removeOrder(Order $order): self
{
if ($this->orders->removeElement($order)) {
// set the owning side to null (unless already changed)
if ($order->getDeliverer() === $this) {
$order->setDeliverer(null);
}
}
return $this;
}
public function getVehicle(): ?Vehicle
{
return $this->vehicle;
}
public function setVehicle(?Vehicle $vehicle): self
{
$this->vehicle = $vehicle;
return $this;
}
public function getNbRate(): ?int
{
return $this->nbRate;
}
public function setNbRate(int $nbRate): self
{
$this->nbRate += 1;
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
}
User.php
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
#[ORM\Entity(repositoryClass: UserRepository::class)]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 180, unique: true)]
private ?string $email = null;
#[ORM\Column]
private array $roles = [];
/**
* #var string The hashed password
*/
#[ORM\Column]
private ?string $password = null;
#[ORM\Column(length: 255)]
private ?string $address = null;
#[ORM\ManyToMany(targetEntity: Promotion::class, inversedBy: 'users')]
private Collection $promotion;
#[ORM\OneToOne(mappedBy: 'user', cascade: ['persist', 'remove'])]
private ?RestaurantInfo $restaurantInfo = null;
#[ORM\OneToMany(mappedBy: 'user', targetEntity: Order::class)]
private Collection $orders;
#[ORM\Column(length: 255)]
private ?string $firstName = null;
#[ORM\Column(length: 255)]
private ?string $lastName = null;
#[ORM\Column(length: 255)]
private ?string $phoneNumber = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
private ?\DateTimeInterface $birthDate = null;
#[ORM\ManyToMany(targetEntity: Restaurant::class, inversedBy: 'users')]
private Collection $favorites;
#[ORM\OneToOne(mappedBy: 'user', cascade: ['persist', 'remove'])]
private ?Deliverer $deliverer = null;
public function __construct()
{
$this->promotion = new ArrayCollection();
$this->orders = new ArrayCollection();
$this->favorites = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* #see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->email;
}
/**
* #deprecated since Symfony 5.3, use getUserIdentifier instead
*/
public function getUsername(): string
{
return (string) $this->email;
}
/**
* #see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
if($roles == null)
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* #see PasswordAuthenticatedUserInterface
*/
public function getPassword(): string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* Returning a salt is only needed, if you are not using a modern
* hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
*
* #see UserInterface
*/
public function getSalt(): ?string
{
return null;
}
/**
* #see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getAddress(): ?string
{
return $this->address;
}
public function setAddress(string $address): self
{
$this->address = $address;
return $this;
}
/**
* #return Collection<int, Promotion>
*/
public function getPromotion(): Collection
{
return $this->promotion;
}
public function addPromotion(Promotion $promotion): self
{
if (!$this->promotion->contains($promotion)) {
$this->promotion->add($promotion);
}
return $this;
}
public function removePromotion(Promotion $promotion): self
{
$this->promotion->removeElement($promotion);
return $this;
}
public function getRestaurantInfo(): ?RestaurantInfo
{
return $this->restaurantInfo;
}
public function setRestaurantInfo(?RestaurantInfo $restaurantInfo): self
{
// unset the owning side of the relation if necessary
if ($restaurantInfo === null && $this->restaurantInfo !== null) {
$this->restaurantInfo->setUser(null);
}
// set the owning side of the relation if necessary
if ($restaurantInfo !== null && $restaurantInfo->getUser() !== $this) {
$restaurantInfo->setUser($this);
}
$this->restaurantInfo = $restaurantInfo;
return $this;
}
/**
* #return Collection<int, Order>
*/
public function getOrders(): Collection
{
return $this->orders;
}
public function addOrder(Order $order): self
{
if (!$this->orders->contains($order)) {
$this->orders->add($order);
$order->setUser($this);
}
return $this;
}
public function removeOrder(Order $order): self
{
if ($this->orders->removeElement($order)) {
// set the owning side to null (unless already changed)
if ($order->getUser() === $this) {
$order->setUser(null);
}
}
return $this;
}
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(string $firstName): self
{
$this->firstName = $firstName;
return $this;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(string $lastName): self
{
$this->lastName = $lastName;
return $this;
}
public function getPhoneNumber(): ?string
{
return $this->phoneNumber;
}
public function setPhoneNumber(string $phoneNumber): self
{
$this->phoneNumber = $phoneNumber;
return $this;
}
public function getBirthDate(): ?\DateTimeInterface
{
return $this->birthDate;
}
public function setBirthDate(\DateTimeInterface $birthDate): self
{
$this->birthDate = $birthDate;
return $this;
}
public function __toString()
{
return (string) $this->getId();
}
/**
* #return Collection<int, Restaurant>
*/
public function getFavorites(): Collection
{
return $this->favorites;
}
public function addFavorite(Restaurant $favorite): self
{
if (!$this->favorites->contains($favorite)) {
$this->favorites->add($favorite);
}
return $this;
}
public function removeFavorite(Restaurant $favorite): self
{
$this->favorites->removeElement($favorite);
return $this;
}
public function getDeliverer(): ?Deliverer
{
return $this->deliverer;
}
public function setDeliverer(?Deliverer $deliverer): self
{
// unset the owning side of the relation if necessary
if ($deliverer === null && $this->deliverer !== null) {
$this->deliverer->setUser(null);
}
// set the owning side of the relation if necessary
if ($deliverer !== null && $deliverer->getUser() !== $this) {
$deliverer->setUser($this);
}
$this->deliverer = $deliverer;
return $this;
}
}
UserController.php
<?php
namespace App\Controller;
use App\Entity\Deliverer;
use App\Entity\User;
use App\Form\UserType;
use App\Repository\UserRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* #Route("/user")
*/
class UserController extends AbstractController
{
/**
* #Route("/", name="app_user_index", methods={"GET"})
*/
public function index(UserRepository $userRepository): Response
{
// $user = $this->getUser();
// return $this->render('user/index.html.twig', [
// 'user' => $user,
// ]);
return $this->render('user/index.html.twig', [
'users' => $userRepository->findAll(),
]);
}
/**
* #Route("/new", name="app_user_new", methods={"GET", "POST"})
*/
public function new(Request $request, UserRepository $userRepository): Response
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$userRepository->add($user, true);
return $this->redirectToRoute('app_user_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('user/new.html.twig', [
'user' => $user,
'form' => $form,
]);
}
/**
* #Route("/{id}", name="app_user_show", methods={"GET"})
*/
public function show(User $user, $id): Response
{
$vehicle = 1;
$vehicle = 1;
$user_session = $this->getUser();
$deliverer = $user->getDeliverer();
if ($deliverer) {
$vehicle = $deliverer->getVehicle();
$orders = $deliverer->getOrders();
}
$favorites = $user->getFavorites();
// Profil utilisateur seulement accessible à celui qui est connecté. Si url modifier avec un id d'un autre user on en peut pas voir le profil de l'autre
if ($user_session->getId() == intval($id)) {
return $this->render('user/show.html.twig', [
'user' => $user,
'deliverer' => $deliverer,
'vehicle' => $vehicle,
'orders' => $orders,
'favorites' => $favorites,
]);
}
$id = 1000;
return $this->render('user/show.html.twig', [
'user' => $user_session,
'deliverer' => $deliverer,
'vehicle' => $vehicle,
'orders' => $orders,
'favorites' => $favorites,
]);
}
/**
* #Route("/{id}/edit", name="app_user_edit", methods={"GET", "POST"})
*/
public function edit(Request $request, User $user, UserRepository $userRepository): Response
{
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$userRepository->add($user, true);
return $this->redirectToRoute('app_user_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('user/edit.html.twig', [
'user' => $user,
'form' => $form,
]);
}
/**
* #Route("/{id}", name="app_user_delete", methods={"POST"})
*/
public function delete(Request $request, User $user, UserRepository $userRepository): Response
{
if ($this->isCsrfTokenValid('delete' . $user->getId(), $request->request->get('_token')))
{
$userRepository->remove($user, true);
}
return $this->redirectToRoute('app_user_index', [], Response::HTTP_SEE_OTHER);
}
}
DelivererController.php
<?php
namespace App\Controller;
use App\Entity\Deliverer;
use App\Form\DelivererType;
use App\Repository\DelivererRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
/**
* #Route("/deliverer")
*/
class DelivererController extends AbstractController
{
/**
* #Route("/", name="app_deliverer_index", methods={"GET"})
*/
public function index(DelivererRepository $delivererRepository): Response
{
$user = $this->getUser();
return $this->render('deliverer/index.html.twig', [
'deliverers' => $delivererRepository->findAll(),
'user' => $user,
]);
}
/**
* #Route("/new", name="app_deliverer_new", methods={"GET", "POST"})
*/
public function new(Request $request, DelivererRepository $delivererRepository, EntityManagerInterface $entityManager): Response
{
$user = $this->getUser();
$user_id = $user->getId();
$user_roles = $user->getRoles();
// Si l'utilisateur est déjà un livreur impossible de le devenir, retourne à sa page profil
if (in_array('ROLE_LIVREUR', $user_roles)) {
return $this->redirectToRoute('app_user_show', ['id' => $user_id]);
}
$deliverer = new Deliverer();
$form = $this->createForm(DelivererType::class, $deliverer);
$form->handleRequest($request);
$id = 1326580;
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($deliverer);
$id = 1000;
$user->setRoles(array('ROLE_USER', 'ROLE_LIVREUR'));
$user->setDeliverer($deliverer);
$entityManager->persist($user);
$entityManager->flush();
// Reload user authentification with new roles. If not error to resdirection because user entity is null
$token = new UsernamePasswordToken($this->getUser(), null, 'main', $this->getUser()->getRoles());
$this->get('security.token_storage')->setToken($token);
$user_id = $this->get('security.token_storage')->getToken()->getUser()->getId();
$user = $this->getUser();
return $this->redirectToRoute('app_user_show', ['id' => $user_id]);
}
return $this->renderForm('deliverer/new.html.twig', [
'deliverer' => $deliverer,
'form' => $form,
'user' => $user,
'id' => $id,
]);
}
/**
* #Route("/{id}", name="app_deliverer_show", methods={"GET"})
*/
public function show(Deliverer $deliverer): Response
{
$user = $this->getUser();
return $this->render('deliverer/show.html.twig', [
'deliverer' => $deliverer,
'user' => $user,
]);
}
/**
* #Route("/{id}/edit", name="app_deliverer_edit", methods={"GET", "POST"})
*/
public function edit(Request $request, Deliverer $deliverer, DelivererRepository $delivererRepository): Response
{
$form = $this->createForm(DelivererType::class, $deliverer);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$delivererRepository->add($deliverer, true);
$user_id = $this->get('security.token_storage')->getToken()->getUser()->getId();
return $this->redirectToRoute('app_user_show', ['id' => $user_id]);
// return $this->redirectToRoute('app_deliverer_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('deliverer/edit.html.twig', [
'deliverer' => $deliverer,
'form' => $form,
]);
}
/**
* #Route("/{id}", name="app_deliverer_delete", methods={"POST"})
*/
public function delete(Request $request, Deliverer $deliverer, DelivererRepository $delivererRepository): Response
{
if ($this->isCsrfTokenValid('delete'.$deliverer->getId(), $request->request->get('_token'))) {
$delivererRepository->remove($deliverer, true);
}
return $this->redirectToRoute('app_deliverer_index', [], Response::HTTP_SEE_OTHER);
}
}
Deliverer.php
remplace
[ORM\OneToOne(inversedBy: 'deliverer', cascade: ['persist', 'remove'])]
by
[ORM\OneToOne(inversedBy: 'deliverer', cascade: ['persist'])]
<?php
namespace App\Entity;
use App\Repository\DelivererRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: DelivererRepository::class)]
class Deliverer
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(type: Types::DECIMAL, precision: 3, scale: 1, nullable: true)]
private ?string $rate = null;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $info = null;
#[ORM\OneToMany(mappedBy: 'deliverer', targetEntity: Order::class)]
private Collection $orders;
#[ORM\ManyToOne(inversedBy: 'deliverers')]
private ?Vehicle $vehicle = null;
#[ORM\Column]
private ?int $nbRate = 0;
#[ORM\OneToOne(inversedBy: 'deliverer', cascade: ['persist'])]
private ?User $user = null;
...
to complete #Yusuf answer:
Thanks to cascade: remove, you can easily delete a user and all linked comments without having to loop through them:
https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations
In your annotation, you just need to remove the option "remove" in the cascade option.
My Entity Item has a Repository (ItemRepository) with the function findItemCount(). When I use
$repository = $em->getRepository(Item::class);
$items = $repository->findItemCount();
I get the warning:
Potentially polymorphic call. The code may be inoperable depending on the actual class instance passed as the argument.
Also the auto completion doesn't suggest me the function "findItemCount". What is my mistake?
Controller:
/**
* Artikel Liste
* #Route("/item/list", name="app_item_list")
* #param EntityManagerInterface $em
* #return Response
*/
public function listItems(EntityManagerInterface $em): Response
{
$repository = $em->getRepository(Item::class);
$items = $repository->findItemCount();
return $this->render('item_admin/itemList.html.twig', [
'items' => $items,
'title' => 'Artikel Übersicht',
'blocked' => false
]);
}
Item.php
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\OrderBy;
/**
* #ORM\Entity(repositoryClass="App\Repository\ItemRepository")
*/
class Item
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
* #OrderBy({"name" = "ASC"})
*/
private $name;
/**
* #ORM\Column(type="text", nullable=true)
*/
private $description;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Itemparent", inversedBy="item")
*/
private $itemparent;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Itemgroup", inversedBy="items")
*/
private $itemgroup;
/**
* #ORM\Column(type="string", length=255)
*/
private $minsize;
/**
* #ORM\Column(type="boolean")
*/
private $charge;
/**
* #ORM\Column(type="boolean")
*/
private $blocked;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Barcode", mappedBy="item", orphanRemoval=true)
*/
private $barcodes;
/**
* #ORM\OneToMany(targetEntity="App\Entity\ItemStock", mappedBy="item", orphanRemoval=true)
*/
private $itemStocks;
/**
* #ORM\OneToMany(targetEntity="App\Entity\BookingItem", mappedBy="item", orphanRemoval=true)
*/
private $bookingItems;
/**
* #ORM\Column(type="float", nullable=true)
*/
private $price;
/**
* #ORM\OneToMany(targetEntity=SupplierItems::class, mappedBy="item")
*/
private $supplierItems;
/**
* #ORM\OneToMany(targetEntity=ItemStockCharge::class, mappedBy="item")
*/
private $itemStockCharges;
public function __construct()
{
$this->barcodes = new ArrayCollection();
$this->itemStocks = new ArrayCollection();
$this->suppliers = new ArrayCollection();
$this->supplierItems = new ArrayCollection();
$this->itemStockCharges = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getItemparent(): ?Itemparent
{
return $this->itemparent;
}
public function setItemparent(?Itemparent $itemparent): self
{
$this->itemparent = $itemparent;
return $this;
}
public function getItemgroup(): ?Itemgroup
{
return $this->itemgroup;
}
public function setItemgroup(?Itemgroup $itemgroup): self
{
$this->itemgroup = $itemgroup;
return $this;
}
public function getMinsize(): ?string
{
return $this->minsize;
}
public function setMinsize(string $minsize): self
{
$this->minsize = $minsize;
return $this;
}
public function getCharge(): ?bool
{
return $this->charge;
}
public function setCharge(bool $charge): self
{
$this->charge = $charge;
return $this;
}
public function getBlocked(): ?bool
{
return $this->blocked;
}
public function setBlocked(bool $blocked): self
{
$this->blocked = $blocked;
return $this;
}
/**
* #return Collection|Barcode[]
*/
public function getBarcodes(): Collection
{
return $this->barcodes;
}
public function addBarcode(Barcode $barcode): self
{
if (!$this->barcodes->contains($barcode)) {
$this->barcodes[] = $barcode;
$barcode->setItem($this);
}
return $this;
}
public function removeBarcode(Barcode $barcode): self
{
if ($this->barcodes->contains($barcode)) {
$this->barcodes->removeElement($barcode);
// set the owning side to null (unless already changed)
if ($barcode->getItem() === $this) {
$barcode->setItem(null);
}
}
return $this;
}
/**
* #return Collection|ItemStock[]
*/
public function getItemStocks(): Collection
{
return $this->itemStocks;
}
public function addItemStock(ItemStock $itemStock): self
{
if (!$this->itemStocks->contains($itemStock)) {
$this->itemStocks[] = $itemStock;
$itemStock->setItem($this);
}
return $this;
}
public function removeItemStock(ItemStock $itemStock): self
{
if ($this->itemStocks->contains($itemStock)) {
$this->itemStocks->removeElement($itemStock);
// set the owning side to null (unless already changed)
if ($itemStock->getItem() === $this) {
$itemStock->setItem(null);
}
}
return $this;
}
/**
* #return Collection|BookingItem[]
*/
public function getBookingItems(): Collection
{
return $this->bookingItems;
}
public function addBookingItem(BookingItem $bookingItem): self
{
if (!$this->bookingItems->contains($bookingItem)) {
$this->bookingItems[] = $bookingItem;
$bookingItem->setItem($this);
}
return $this;
}
public function removeBookingItem(BookingItem $bookingItem): self
{
if ($this->bookingItems->contains($bookingItem)) {
$this->bookingItems->removeElement($bookingItem);
if ($bookingItem->getItem() === $this) {
$bookingItem->setItem(null);
}
}
return $this;
}
public function getPrice(): ?float
{
return $this->price;
}
public function setPrice(?float $price): self
{
$this->price = $price;
return $this;
}
public function getCommaPrice(): string
{
return number_format($this->price, 2, ',', '');
}
/**
* #return Collection|SupplierItems[]
*/
public function getSupplierItems(): Collection
{
return $this->supplierItems;
}
public function addSupplierItem(SupplierItems $supplierItem): self
{
if (!$this->supplierItems->contains($supplierItem)) {
$this->supplierItems[] = $supplierItem;
$supplierItem->setItem($this);
}
return $this;
}
public function removeSupplierItem(SupplierItems $supplierItem): self
{
if ($this->supplierItems->contains($supplierItem)) {
$this->supplierItems->removeElement($supplierItem);
// set the owning side to null (unless already changed)
if ($supplierItem->getItem() === $this) {
$supplierItem->setItem(null);
}
}
return $this;
}
/**
* #return Collection|ItemStockCharge[]
*/
public function getItemStockCharges(): Collection
{
return $this->itemStockCharges;
}
public function addItemStockCharge(ItemStockCharge $itemStockCharge): self
{
if (!$this->itemStockCharges->contains($itemStockCharge)) {
$this->itemStockCharges[] = $itemStockCharge;
$itemStockCharge->setItem($this);
}
return $this;
}
public function removeItemStockCharge(ItemStockCharge $itemStockCharge): self
{
if ($this->itemStockCharges->contains($itemStockCharge)) {
$this->itemStockCharges->removeElement($itemStockCharge);
// set the owning side to null (unless already changed)
if ($itemStockCharge->getItem() === $this) {
$itemStockCharge->setItem(null);
}
}
return $this;
}
}
ItemRepository.php
<?php
namespace App\Repository;
use App\Entity\Item;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
/**
* #method Item|null find($id, $lockMode = null, $lockVersion = null)
* #method Item|null findOneBy(array $criteria, array $orderBy = null)
* #method Item[] findAll()
* #method Item[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class ItemRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Item::class);
}
public function findItem()
{
return $this->createQueryBuilder('a')
->andWhere('a.blocked = :val')
->setParameter('val', false)
->orderBy('a.name', 'ASC')
->getQuery()
->getResult()
;
}
public function findBlockedItemCount()
{
return $this->createQueryBuilder('item')
->select('item, SUM(stocks.count) as sums')
->andWhere('item.blocked = :val')
->setParameter('val', true)
->leftJoin('item.itemStocks', 'stocks')
->groupBy('item')
->orderBy('item.name', 'ASC')
->getQuery()
->getResult()
;
}
public function findItemCount(){
return $this->createQueryBuilder('item')
->select('item, SUM(stocks.count) as sums')
->andWhere('item.blocked = :val')
->setParameter('val', false)
->leftJoin('item.itemStocks', 'stocks')
->groupBy('item')
->orderBy('item.name', 'ASC')
->getQuery()
->getResult()
;
}
}
The IDE has now way of knowing that $em->getRepository(Item::class); will return ItemRepository, since that's not resolved until runtime.
Inject ItemRepository instead of the entity manager, it's the better practice in any case:
public function listItems(ItemRepository $itemRepository): Response
{
$items = $itemRepository->findItemCount();
// etc
}
First of all, I apologize for my basic use of english, I hope you can understand me.
I'm doing a deployment of a project, the development was on Symfony 5.1, using easyadmin-bundle 3.1, and vich/uploader-bundle 1.15. On my localhost that works great, but when I move to production, on my dashboard, can't 'Create New' or 'Edit' in any entity who has images inside, it throw me this error.
An error has occurred resolving the options of the form "Vich\UploaderBundle\Form\Type\VichImageType": The options "upload_dir", "upload_filename" do not exist.
https://i.ibb.co/gWRjPLm/Screenshot-2020-11-20-An-error-has-occurred-resolving-the-options-of-the-form-Vich-Uploader-Bundle-F.png
The only place I find upload_dir, is inside vendor folder.
https://i.ibb.co/VHw39z5/Screenshot-2020-11-20-Symfony-Profiler.png
My entity
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* #ORM\Entity(repositoryClass=ColoresRepository::class)
* #Vich\Uploadable()
*/
class Colores
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=30)
*/
private $nombre;
/**
* #ORM\Column(type="string", length=100)
*/
private $thumbnail;
/**
* #Vich\UploadableField(mapping="colores", fileNameProperty="thumbnail")
*/
private $thumbnailFile;
/**
* #ORM\Column(type="datetime")
*/
private $updatedAt;
public function __construct()
{
$this->updatedAt = new \DateTime();
}
/**
* #return mixed
*/
public function getThumbnailFile()
{
return $this->thumbnailFile;
}
/**
* #param mixed $thumbnailFile
*/
public function setThumbnailFile($thumbnailFile): void
{
$this->thumbnailFile = $thumbnailFile;
if($thumbnailFile) {
$this->updatedAt = new \DateTime();
}
}
/**
* #return mixed
*/
public function getThumbnail()
{
return $this->thumbnail;
}
/**
* #param mixed $thumbnail
*/
public function setThumbnail($thumbnail): void
{
$this->thumbnail = $thumbnail;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
public function getId(): ?int
{
return $this->id;
}
public function getNombre(): ?string
{
return $this->nombre;
}
public function setNombre(string $nombre): self
{
$this->nombre = $nombre;
return $this;
}
public function __toString()
{
return $this->nombre;
}
}
My Dashboard
<?php
namespace App\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem;
use EasyCorp\Bundle\EasyAdminBundle\Router\CrudUrlGenerator;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Entity\Colores;
class DashboardController extends AbstractDashboardController
{
/**
* #Route("admin", name="admin")
*/
public function index(): Response
{
$routeBuilder = $this->get(CrudUrlGenerator::class)->build();
return $this->redirect($routeBuilder->setController(ColoresCrudController::class)->generateUrl());
}
public function configureDashboard(): Dashboard
{
return Dashboard::new()
->setTitle('Test Site');
}
public function configureMenuItems(): iterable
{
yield MenuItem::section('DESTACADOS');
yield MenuItem::linkToCrud('Colores', 'fa fa-paint-brush', Colores::class);
}
My Crud controller
<?php
namespace App\Controller\Admin;
use App\Entity\Colores;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\ImageField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use Vich\UploaderBundle\Form\Type\VichImageType;
class ColoresCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Colores::class;
}
public function configureFields(string $pageName): iterable
{
return [
TextField::new('nombre'),
ImageField::new('thumbnailFile')
->setFormType(VichImageType::class)->onlyOnForms(),
ImageField::new('thumbnail')
->setBasePath('/images/colores')->hideOnForm()
];
}
}
vich_uploader.yaml
vich_uploader:
db_driver: orm
mappings:
colores:
uri_prefix: /images/colores
upload_destination: '%kernel.project_dir%/public/images/colores'
namer: Vich\UploaderBundle\Naming\UniqidNamer
Using setFormType is an "undocumented hack"
There is an issue with the v3.1.8 and the ImageField.
You can try this syntax :
$filename = ImageField::new('filename', 'File')
->setBasePath('uploads/contact_message')
->setUploadDir('public/uploads/contact_message/');
If it doesn't work you can roll back to v.3.1.7 (force the version in your composer.json) and using the old syntax with 2 field ( the file and the filename)
$avatar = ImageField::new('avatar')->setBasePath('uploads/images/users')->setLabel('Photo');
$avatarFile = ImageField::new('avatarFile')->setFormType(VichImageType::class);
if (Crud::PAGE_INDEX === $pageName) {
return [ $avatar];
} elseif (Crud::PAGE_EDIT=== $pageName) {
return [$avatarFile];
You can create your own Custom Field (see https://symfony.com/doc/current/bundles/EasyAdminBundle/fields.html#creating-custom-fields) like this :
namespace App\Admin\Field;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\FieldTrait;
use Vich\UploaderBundle\Form\Type\VichImageType;
class VichImageField implements FieldInterface
{
use FieldTrait;
public static function new(string $propertyName, ?string $label = null): self
{
return (new self())
->setProperty($propertyName)
->setLabel($label)
->setFormType(VichImageType::class)
->setCustomOption('image_uri', null)
->setCustomOption('download_uri', null)
;
}
public function setImageUri($imageUri): self
{
$this->setCustomOption('image_uri', $imageUri);
return $this;
}
public function setDownloadUri($downloadUri): self
{
$this->setCustomOption('download_uri', $downloadUri);
return $this;
}
}
And the use it in your crud controller configureFileds method :
VichImageField::new('avatarFile', 'Avatar')
->setDownloadUri('public/' . $this->getParameter('app.path.user_avatars'))
->setImageUri($this->getParameter('app.path.user_avatars'))
,
It works with the last EasyAdminBundle > v3.1.7