Problems with Doctrine mapping in Symfony - orm

I have been programming a project in the Symfony 3 using the Doctrine ORM. I have main entity called 'Race', which contains some fields and relations to another entities like 'RaceRelationToType', 'RaceRelationToOrganizer' and so on - you can see it in the picture of the database schema bellow. (Only for information, 'RaceRelationTo*' entities are entities which prevents change of original data.)
The problem: The problem becames when I fetch data from database using $this->em->getRepository('AppBundle:Race')->findAll();. Data in database are stored correctly, but If I fetch them, they have wrong data type. raceRelationToOrganizer variable should be of data type RaceRelationToOrganizer, not RaceRelationToSeason and so on.
Everything had worked right until I reset a database. When I insert new race to cleared database, id of raceRelationToSeason is 1, raceRelationToType is 1, raceRelationToOrganizer is 1 ans so on. Problems occured after reset of database (and reset of auto increment).
If ids of all relations are different, than it works OK. Magic? Error? Does anybody know what to do with it? Can you find some problem in files bellow? I have been trying to solve it for hours. Contents of important files are bellow.
I use yaml configuration files for ORM mapping. Race.orm.yml contains:
AppBundle\Entity\Race:
type: entity
table: race
id:
id:
type: integer
generator:
strategy: AUTO
fields:
registrationNumberOfRace:
column: registration_number_of_race
type: integer
length: 4
nullable: false
dateFrom:
column: date_from
type: date
nullable: false
dateTo:
column: date_to
type: date
nullable: false
manyToOne:
raceRelationToSeason:
targetEntity: AppBundle\Entity\RaceRelationToSeason
joinColumn:
name: race_relation_to_season
referencedColumnName: id
onDelete: RESTRICT
nullable: false
fetch: EAGER
cascade: [ persist,remove ]
raceRelationToType:
targetEntity: AppBundle\Entity\RaceRelationToType
joinColumn:
name: race_relation_to_type
referencedColumnName: id
onDelete: RESTRICT
nullable: false
fetch: EAGER
cascade: [ persist,remove ]
raceRelationToOrganizer:
targetEntity: AppBundle\Entity\RaceRelationToOrganizer
joinColumn:
name: race_relation_to_organizer
referencedColumnName: id
onDelete: RESTRICT
nullable: false
fetch: EAGER
cascade: [ persist,remove ]
raceRelationToVenue:
targetEntity: AppBundle\Entity\RaceRelationToVenue
joinColumn:
name: race_relation_to_venue
referencedColumnName: id
onDelete: RESTRICT
nullable: false
fetch: EAGER
cascade: [ persist,remove ]
Entity Race.php contains:
<?php
namespace AppBundle\Entity;
/**
* Class Race
* #package AppBundle\Entity
*/
class Race
{
/**
* #var integer Id of the race
*/
protected $id;
/**
* #var SeasonOfRace
*/
protected $seasonOfRace;
/**
* #var RaceRelationToSeason
*/
protected $raceRelationToSeason;
/**
* #var TypeOfRace
*/
protected $typeOfRace;
/**
* #var RaceRelationToType
*/
protected $raceRelationToType;
/**
* #var integer Registration number of the race which depend on the type of race
*/
protected $registrationNumberOfRace;
/**
* #var OrganizerOfRace
*/
protected $organizerOfRace;
/**
* #var RaceRelationToOrganizer
*/
protected $raceRelationToOrganizer;
/**
* #var VenueOfRace
*/
protected $venueOfRace;
/**
* #var RaceRelationToVenue
*/
protected $raceRelationToVenue;
/**
* #var \DateTime
*/
protected $dateFrom;
/**
* #var \DateTime
*/
protected $dateTo;
/**
* Race constructor.
*/
public function __construct()
{
$this->dateFrom = $this->dateTo = new \DateTime();
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param $id
* #return $this
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* #return SeasonOfRace
*/
public function getSeasonOfRace()
{
if ($this->raceRelationToSeason) {
if ($this->raceRelationToSeason->getOriginal()) {
$this->seasonOfRace = $this->raceRelationToSeason->getOriginal();
return $this->seasonOfRace;
} else {
return $this->seasonOfRace;
}
} else {
return $this->seasonOfRace;
}
}
/**
* #param SeasonOfRace $seasonOfRace
* #return Race
*/
public function setSeasonOfRace(SeasonOfRace $seasonOfRace)
{
$this->seasonOfRace = $seasonOfRace;
if ($this->seasonOfRace) {
if ($this->raceRelationToSeason) {
$this->raceRelationToSeason->setLabel($this->seasonOfRace->getLabel());
$this->raceRelationToSeason->setShortLabel($this->seasonOfRace->getShortLabel());
$this->raceRelationToSeason->setOriginal($this->seasonOfRace);
} else {
$this->raceRelationToSeason = new RaceRelationToSeason();
$this->raceRelationToSeason->setLabel($this->seasonOfRace->getLabel());
$this->raceRelationToSeason->setShortLabel($this->seasonOfRace->getShortLabel());
$this->raceRelationToSeason->setOriginal($this->seasonOfRace);
}
}
return $this;
}
/**
* #return RaceRelationToSeason
*/
public function getRaceRelationToSeason()
{
return $this->raceRelationToSeason;
}
/**
* #param RaceRelationToSeason $raceRelationToSeason
* #return Race
*/
public function setRaceRelationToSeason(RaceRelationToSeason $raceRelationToSeason)
{
$this->raceRelationToSeason = $raceRelationToSeason;
return $this;
}
/**
* #return TypeOfRace
*/
public function getTypeOfRace()
{
if ($this->raceRelationToType) {
if ($this->raceRelationToType->getOriginal()) {
$this->typeOfRace = $this->raceRelationToType->getOriginal();
return $this->typeOfRace;
} else {
return $this->typeOfRace;
}
} else {
return $this->typeOfRace;
}
}
/**
* #param TypeOfRace $typeOfRace
* #return Race
*/
public function setTypeOfRace(TypeOfRace $typeOfRace)
{
$this->typeOfRace = $typeOfRace;
if ($this->typeOfRace) {
if ($this->raceRelationToType) {
$this->raceRelationToType->setLabel($this->typeOfRace->getLabel());
$this->raceRelationToType->setShortLabel($this->typeOfRace->getShortLabel());
$this->raceRelationToType->setOriginal($this->typeOfRace);
} else {
$this->raceRelationToType = new RaceRelationToType();
$this->raceRelationToType->setLabel($this->typeOfRace->getLabel());
$this->raceRelationToType->setShortLabel($this->typeOfRace->getShortLabel());
$this->raceRelationToType->setOriginal($this->typeOfRace);
}
}
return $this;
}
/**
* #return RaceRelationToType
*/
public function getRaceRelationToType()
{
return $this->raceRelationToType;
}
/**
* #param RaceRelationToType $raceRelationToType
* #return Race
*/
public function setRaceRelationToType(RaceRelationToType $raceRelationToType)
{
$this->raceRelationToType = $raceRelationToType;
return $this;
}
/**
* #return int
*/
public function getRegistrationNumberOfRace()
{
return $this->registrationNumberOfRace;
}
/**
* #param $registrationNumberOfRace
* #return Race
*/
public function setRegistrationNumberOfRace($registrationNumberOfRace)
{
$this->registrationNumberOfRace = $registrationNumberOfRace;
return $this;
}
/**
* #return VenueOfRace
*/
public function getVenueOfRace()
{
if ($this->raceRelationToVenue) {
if ($this->raceRelationToVenue->getOriginal()) {
$this->venueOfRace = $this->raceRelationToVenue->getOriginal();
return $this->venueOfRace;
} else {
return $this->venueOfRace;
}
} else {
return $this->venueOfRace;
}
}
/**
* #param VenueOfRace $venueOfRace
* #return Race
*/
public function setVenueOfRace(VenueOfRace $venueOfRace)
{
$this->venueOfRace = $venueOfRace;
if ($this->venueOfRace) {
if ($this->raceRelationToVenue) {
$this->raceRelationToVenue->setLabel($this->venueOfRace->getLabel());
$this->raceRelationToVenue->setShortLabel($this->venueOfRace->getShortLabel());
$this->raceRelationToVenue->setOriginal($this->venueOfRace);
} else {
$this->raceRelationToVenue = new RaceRelationToVenue();
$this->raceRelationToVenue->setLabel($this->venueOfRace->getLabel());
$this->raceRelationToVenue->setShortLabel($this->venueOfRace->getShortLabel());
$this->raceRelationToVenue->setOriginal($this->venueOfRace);
}
}
return $this;
}
/**
* #return RaceRelationToVenue
*/
public function getRaceRelationToVenue()
{
return $this->raceRelationToVenue;
}
/**
* #param RaceRelationToVenue $raceRelationToVenue
* #return Race
*/
public function setRaceRelationToVenue(RaceRelationToVenue $raceRelationToVenue)
{
$this->raceRelationToVenue = $raceRelationToVenue;
return $this;
}
/**
* #return OrganizerOfRace
*/
public function getOrganizerOfRace()
{
if ($this->raceRelationToOrganizer) {
if ($this->raceRelationToOrganizer->getOriginal()) {
$this->organizerOfRace = $this->raceRelationToOrganizer->getOriginal();
return $this->organizerOfRace;
} else {
return $this->organizerOfRace;
}
} else {
return $this->organizerOfRace;
}
}
/**
* #param OrganizerOfRace $organizerOfRace
* #return Race
*/
public function setOrganizerOfRace(OrganizerOfRace $organizerOfRace)
{
$this->organizerOfRace = $organizerOfRace;
if ($this->organizerOfRace) {
if ($this->raceRelationToOrganizer) {
$this->raceRelationToOrganizer->setLabel($this->organizerOfRace->getLabel());
$this->raceRelationToOrganizer->setShortLabel($this->organizerOfRace->getShortLabel());
$this->raceRelationToOrganizer->setOriginal($this->organizerOfRace);
} else {
$this->raceRelationToOrganizer = new RaceRelationToOrganizer();
$this->raceRelationToOrganizer->setLabel($this->organizerOfRace->getLabel());
$this->raceRelationToOrganizer->setShortLabel($this->organizerOfRace->getShortLabel());
$this->raceRelationToOrganizer->setOriginal($this->organizerOfRace);
}
}
return $this;
}
/**
* #return RaceRelationToOrganizer
*/
public function getRaceRelationToOrganizer()
{
return $this->raceRelationToOrganizer;
}
/**
* #param RaceRelationToOrganizer $raceRelationToOrganizer
* #return Race
*/
public function setRaceRelationToOrganizer(RaceRelationToOrganizer $raceRelationToOrganizer)
{
$this->raceRelationToOrganizer = $raceRelationToOrganizer;
return $this;
}
/**
* #return \DateTime
*/
public function getDateFrom()
{
return $this->dateFrom;
}
/**
* #param \DateTime $dateFrom
* #return $this
*/
public function setDateFrom(\DateTime $dateFrom)
{
$this->dateFrom = $dateFrom;
return $this;
}
/**
* #return \DateTime
*/
public function getDateTo()
{
return $this->dateTo;
}
/**
* #param \DateTime $dateTo
*/
public function setDateTo(\DateTime $dateTo)
{
$this->dateTo = $dateTo;
}
}

I solved it exactly after 23 hours, it was my fault. I want to say sorry to all who have spent their time with trying to help me.
As you can see in the database schema above, there is the table RaceRelationToType that is table between table called Race and table called TypeOfRace. This table is here because when you remove original data from TypeOfRace, data are still stored in a copy in RaceRelationToType+ - it is because of archiving data. It is same with another tables beggining with RaceRelationToXXX.
Mistake was in RaceRelationToOrganizer.php entity. I had extended RaceRelationToOrganizer entity with VenueOfRace entity instead of OrganizerOfRace entity. I don't know why, but It had worked before, but not after reset of database.
So there was no error shown, but Doctrine didn't know what to do with it (fields in all this between-tables are identical) and it mapped random data types. So that's all.
Thank you and sorry!

Related

Doctrine custom entity repository (QueryBuilder)

Howe create custom repository QueryBuilder for Room entity, witch will return all available rooms between two dates. I have two Entities Room.php and Reservation.php In RoomRepository.php i create function findAvailableRooms($from, $to) Hove i create query builder who return all rooms who do not have a reservation in the selected period? Tnx Room.php
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Controller\AvailableRoom;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Bridge\Doctrine\IdGenerator\UuidV4Generator;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Uid\Uuid;
use App\Repository\RoomRepository;
use Doctrine\ORM\Mapping as ORM;
use App\Controller\AvailableRoomController;
/**
* #ApiResource(
* normalizationContext={"groups"={"room:read"}},
* denormalizationContext={"groups"={"room:write"}},
* attributes={
* "pagination_client_items_per_page"=true
* },
* collectionOperations={
* "get",
* "post",
* "get_available"={
* "method"="GET",
* "path"="/rooms/available/{from}/{to}",
* "controller"=AvailableRoomController::class
* }
* }
* )
* #ORM\Entity(repositoryClass=RoomRepository::class)
*/
class Room
{
/**
* #ORM\Id
* #ORM\Column(type="uuid", unique=true)
* #ORM\GeneratedValue(strategy="CUSTOM")
* #ORM\CustomIdGenerator(class=UuidV4Generator::class)
* #Groups({"room:read"})
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
* #Groups({"room:read", "room:write", "reservation:read"})
*/
private $name;
/**
* #ORM\Column(type="string", length=255)
* #Gedmo\Slug(fields={"name"})
* #Groups({"room:read", "room:write"})
*/
private $slug;
/**
* #ORM\Column(type="text", nullable=true)
* #Groups({"room:read", "room:write"})
*/
private $description;
/**
* #ORM\Column(type="datetime")
* #Gedmo\Timestampable(on="create")
* #Groups({"room:read", "room:write"})
*/
private $createdAt;
/**
* #ORM\Column(type="datetime")
* #Gedmo\Timestampable(on="update")
* #Groups({"room:read", "room:write"})
*/
private $updatedAt;
/**
* #ORM\OneToMany(targetEntity=Reservation::class, mappedBy="room")
* #Groups({"room:read", "room:write"})
*/
private $reservations;
public function __construct()
{
$this->reservations = new ArrayCollection();
}
public function getId(): ?Uuid
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getSlug(): ?string
{
return $this->slug;
}
public function setSlug(string $slug): self
{
$this->slug = $slug;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(?\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(?\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* #return Collection|Reservation[]
*/
public function getReservations(): Collection
{
return $this->reservations;
}
public function addReservation(Reservation $reservation): self
{
if (!$this->reservations->contains($reservation)) {
$this->reservations[] = $reservation;
$reservation->setRoom($this);
}
return $this;
}
public function removeReservation(Reservation $reservation): self
{
if ($this->reservations->removeElement($reservation)) {
// set the owning side to null (unless already changed)
if ($reservation->getRoom() === $this) {
$reservation->setRoom(null);
}
}
return $this;
}
}
Reservation.php
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\DateFilter;
use App\Repository\ReservationRepository;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Bridge\Doctrine\IdGenerator\UuidV4Generator;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Uid\Uuid;
/**
* #ApiResource(
* normalizationContext={"groups"={"reservation:read"}},
* denormalizationContext={"groups"={"reservation:write"}},
* attributes={
* "pagination_client_items_per_page"=true
* }
* )
* #ApiFilter(DateFilter::class, properties={"dateFrom"})
* #ORM\Entity(repositoryClass=ReservationRepository::class)
*/
class Reservation
{
/**
* #ORM\Id
* #ORM\Column(type="uuid", unique=true)
* #ORM\GeneratedValue(strategy="CUSTOM")
* #ORM\CustomIdGenerator(class=UuidV4Generator::class)
* #Groups({"reservation:read"})
*/
private $id;
/**
* #ORM\Column(type="date")
* #Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $dateFrom;
/**
* #ORM\Column(type="date")
* #Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $dateTo;
/**
* #ORM\Column(type="json", nullable=true)
* #Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $meta = [];
/**
* #ORM\ManyToOne(targetEntity=Room::class, inversedBy="reservations")
* #Groups({"reservation:read", "reservation:write"})
*/
private $room;
/**
* #ORM\Column(type="datetime")
* #Gedmo\Timestampable(on="create")
* #Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $createdAt;
/**
* #ORM\Column(type="datetime")
* #Gedmo\Timestampable(on="update")
* #Groups({"reservation:read", "reservation:write", "room:read"})
*/
private $updatedAt;
public function getId(): ?Uuid
{
return $this->id;
}
public function getDateFrom(): ?\DateTimeInterface
{
return $this->dateFrom;
}
public function setDateFrom(\DateTimeInterface $dateFrom): self
{
$this->dateFrom = $dateFrom;
return $this;
}
public function getDateTo(): ?\DateTimeInterface
{
return $this->dateTo;
}
public function setDateTo(\DateTimeInterface $dateTo): self
{
$this->dateTo = $dateTo;
return $this;
}
public function getMeta(): ?array
{
return $this->meta;
}
public function setMeta(?array $meta): self
{
$this->meta = $meta;
return $this;
}
public function getRoom(): ?Room
{
return $this->room;
}
public function setRoom(?Room $room): self
{
$this->room = $room;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(?\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(?\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
}
Something like the following method placed in your ReservationRepository will fetch the ids of Rooms having a Reservation overlapping a specified date range:
/**
* #param \DateTimeInterface $start
* #param \DateTimeInterface $end
*
* #return array
*/
public function findRoomIdsReservedInDateRange(\DateTimeInterface $start, \DateTimeInterface $end)
{
$result = $this
->createQueryBuilder('r')
->select('r.room.id')
->andWhere('r.dateFrom < :end')
->andWhere('r.dateTo > :start')
->setParameter('start', $start)
->setParameter('end', $end)
->orderBy('r.room.id', 'ASC')
->getQuery()
->getScalarResult()
; // [['id' => 1], ['id' => 2], ['id' => 2], ['id' => 5]]
return array_unique(array_column($result, 'id')); // [1, 2, 5]
}
Then you could call that method from your RoomRepository
$exclude = $reservationRepository->findRoomIdsReservedInDateRange($start, $end);
return $this
->createQueryBuilder('room')
->andWhere('room.id not in :array')
->setParameter('array', $exclude)
->getQuery()
->getResult()
;

Syntax Error - line 0, col 122: Error: Expected end of string, got 'ON'

I'm trying to use ON in my Query Builder but it returns [Syntax Error] line 0, col 122: Error: Expected end of string, got 'ON'.
Code:
public function filterChamados(Request $request)
{
$em = $this->getDoctrine()->getManager()->getRepository(Chamados::class)
->createQueryBuilder('c')->select('c.id, d.name_fantasy, c.status, c.titulo, c.description')
->join(Clients::class, 'd',Join::ON,'c.id_client = d.id');
if ($request->request->get('status')) {
$em->where('c.status = :status')
->setParameter('status', $request->request->get('status'));
};
if (strtoupper(trim($request->get('client')))) {
$em->andWhere('(d.name_fantasy=:client OR d.razao_social=:client)')
->setParameter('client', strtoupper(trim($request->get('client'))));
};
if ($request->get('open_date')) {
$em->andWhere('c.open_date >=:open_date')
->setParameter('open_date', $request->get('open_date'));
}
if ($request->get('close_date')) {
$em->andWhere('c.close_date <=:close_date')
->setParameter('close_date', $request->get('close_date'));
}
$em->getQuery()->getArrayResult();
return new JsonResponse($em);
}
If I return its DQL, I get:
SELECT c.id, d.name_fantasy, c.status, c.titulo, c.description FROM App\Entity\Chamados c INNER JOIN App\Entity\Clients d ON c.id_client = d.id WHERE (d.name_fantasy=:client OR d.razao_social=:client)
If I run the SQL directly into PGAdmin, it works.
If I change ON to WITH, it does not return errors, but the result comes empty. Plus, I can't run its SQL directly into PGAdmin.
What am I doing wrong?
EDIT:
This is my raw SQL (considering I'm using all fields):
SELECT
c.id, d.name_fantasy, c. status, c.titulo, c.description
FROM
chamados c
JOIN
clients d
ON
c.id_client_id = d.id
WHERE
c.status = 2 --:status
AND
(d.name_fantasy = 'FARMÁCIA ALGUMA COISA' OR d.razao_social = 'FARMÁCIA ALGUMA COISA') -- :client
AND
c.open_date >= '2019-03-03 10:00' --:open_date
AND
c.close_date <= '2019-09-03 18:00' --:close_date
Entity Chamados:
/**
* #ORM\Entity(repositoryClass="App\Repository\ChamadosRepository")
*/
class Chamados
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string")
*/
private $titulo;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Clients", inversedBy="chamados")
* #ORM\JoinColumn(nullable=false)
*/
private $id_client;
/**
* #ORM\Column(type="integer", options={"default" = 0})
*/
private $status;
/**
* #ORM\Column(type="text", nullable=true)
*/
private $description;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\User", inversedBy="chamados")
*/
private $user;
/**
* #ORM\Column(type="datetime")
*/
private $open_date;
/**
* #ORM\Column(type="datetime", nullable=true)
*/
private $update_date;
/**
* #ORM\Column(type="datetime", nullable=true)
*/
private $close_date;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Tramite", mappedBy="chamado")
*/
private $tramites;
public function __construct()
{
$this->user = new ArrayCollection();
$this->tramites = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getIdClient(): ?Clients
{
return $this->id_client;
}
public function setIdClient(?Clients $id_client): self
{
$this->id_client = $id_client;
return $this;
}
public function getStatus(): ?int
{
return $this->status;
}
public function setStatus(int $status): self
{
$this->status = $status;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
/**
* #return Collection|User[]
*/
public function getUser(): Collection
{
return $this->user;
}
public function addUser(User $user): self
{
if (!$this->user->contains($user)) {
$this->user[] = $user;
}
return $this;
}
public function removeUser(User $user): self
{
if ($this->user->contains($user)) {
$this->user->removeElement($user);
}
return $this;
}
public function getOpenDate(): ?DateTimeInterface
{
return $this->open_date;
}
public function setOpenDate(DateTimeInterface $open_date): self
{
$this->open_date = $open_date;
return $this;
}
public function getUpdateDate(): ?DateTimeInterface
{
return $this->update_date;
}
public function setUpdateDate(?DateTimeInterface $update_date): self
{
$this->update_date = $update_date;
return $this;
}
public function getCloseDate(): ?DateTimeInterface
{
return $this->close_date;
}
public function setCloseDate(?DateTimeInterface $close_date): self
{
$this->close_date = $close_date;
return $this;
}
/**
* #return mixed
*/
public function getTitulo()
{
return $this->titulo;
}
/**
* #param mixed $titulo
* #return Chamados
*/
public function setTitulo($titulo)
{
$this->titulo = $titulo;
return $this;
}
/**
* #return Collection|Tramite[]
*/
public function getTramites(): Collection
{
return $this->tramites;
}
public function addTramite(Tramite $tramite): self
{
if (!$this->tramites->contains($tramite)) {
$this->tramites[] = $tramite;
$tramite->setChamado($this);
}
return $this;
}
public function removeTramite(Tramite $tramite): self
{
if ($this->tramites->contains($tramite)) {
$this->tramites->removeElement($tramite);
// set the owning side to null (unless already changed)
if ($tramite->getChamado() === $this) {
$tramite->setChamado(null);
}
}
return $this;
}
}
Entity Clients:
/**
* #ORM\Entity(repositoryClass="App\Repository\ClientsRepository")
*/
class Clients
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $name_fantasy;
/**
* #ORM\Column(type="string", length=255)
*/
private $razao_social;
/**
* #ORM\Column(type="string", length=128, nullable=true)
*/
private $contact_email;
/**
* #ORM\Column(type="string", length=16, nullable=true)
*/
private $contact_telephone;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Chamados", mappedBy="id_client")
*/
private $chamados;
/**
* #ORM\Column(type="boolean", options={"default"="true"})
*/
private $active;
public function __construct()
{
$this->chamados = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getNameFantasy(): ?string
{
return $this->name_fantasy;
}
public function setNameFantasy(string $name_fantasy): self
{
$this->name_fantasy = mb_convert_case($name_fantasy, MB_CASE_UPPER, 'UTF-8');
return $this;
}
public function getRazaoSocial(): ?string
{
return $this->razao_social;
}
public function setRazaoSocial(string $razao_social): self
{
$this->razao_social = mb_convert_case($razao_social, MB_CASE_UPPER, 'UTF-8');
return $this;
}
public function getContactEmail(): ?string
{
return $this->contact_email;
}
public function setContactEmail(?string $contact_email): self
{
$this->contact_email = $contact_email;
return $this;
}
public function getContactTelephone(): ?string
{
return $this->contact_telephone;
}
public function setContactTelephone(?string $contact_telephone): self
{
$this->contact_telephone = $contact_telephone;
return $this;
}
/**
* #return Collection|Chamados[]
*/
public function getChamados(): Collection
{
return $this->chamados;
}
public function addChamado(Chamados $chamado): self
{
if (!$this->chamados->contains($chamado)) {
$this->chamados[] = $chamado;
$chamado->setIdClient($this);
}
return $this;
}
public function removeChamado(Chamados $chamado): self
{
if ($this->chamados->contains($chamado)) {
$this->chamados->removeElement($chamado);
// set the owning side to null (unless already changed)
if ($chamado->getIdClient() === $this) {
$chamado->setIdClient(null);
}
}
return $this;
}
/**
* #return mixed
*/
public function getActive()
{
return $this->active;
}
/**
* #param mixed $active
* #return Clients
*/
public function setActive($active)
{
$this->active = $active;
return $this;
}
}
Edit 2:
The error is gone and the query is being built properly, but the result is empty.
Controller:
public function filterChamados(Request $request)
{
$em = $this->getDoctrine()->getManager()->getRepository(Chamados::class)
->createQueryBuilder('c')->select('c.id, d.name_fantasy, c.status, c.titulo, c.description')
->join('c.id_client', 'd');
if ($request->request->get('status')) {
$em->where('c.status = :status')
->setParameter('status', $request->request->get('status'));
}
if (strtoupper(trim($request->get('client')))) {
$em->andWhere('(d.name_fantasy=:client OR d.razao_social=:client)')
->setParameter('client', strtoupper(trim($request->get('client'))));
}
if ($request->get('open_date')) {
$em->andWhere('c.open_date >=:open_date')
->setParameter('open_date', $request->get('open_date'));
}
if ($request->get('close_date')) {
$em->andWhere('c.close_date <=:close_date')
->setParameter('close_date', $request->get('close_date'));
}
$em->getQuery()->getArrayResult();
return new JsonResponse($em);
}
Generated query:
[2019-08-21 17:22:31] doctrine.DEBUG: SELECT c0_.id AS id_0, c1_.name_fantasy AS name_fantasy_1, c0_.status AS status_2, c0_.titulo AS titulo_3, c0_.description AS description_4 FROM chamados c0_ INNER JOIN clients c1_ ON c0_.id_client_id = c1_.id WHERE (c1_.name_fantasy = ? OR c1_.razao_social = ?) ["PADARIA","PADARIA"] []
PgAdmin3: If I put both values inside the query and replace " by ', it works, otherwise it returns column "PADARIA" does not exist.
Inside AJAX request: it returns an empty JSON.
For some reason you have a semicolon where it should not be, try the following function, not saying it will work though:
function filterChamados(Request $request)
{
$em = $this->getDoctrine()->getManager()->getRepository(Chamados::class)
->createQueryBuilder('c')->select('c.id, d.name_fantasy, c.status, c.titulo, c.description')
->join('c.Clients', 'd', Join::ON, 'c.id_client = d.id');
if ($request->request->get('status')) {
$em->where('c.status = :status')
->setParameter('status', $request->request->get('status'));
}
if (strtoupper(trim($request->get('client')))) {
$em->andWhere('(d.name_fantasy=:client OR d.razao_social=:client)')
->setParameter('client', strtoupper(trim($request->get('client'))));
}
if ($request->get('open_date')) {
$em->andWhere('c.open_date >=:open_date')
->setParameter('open_date', $request->get('open_date'));
}
if ($request->get('close_date')) {
$em->andWhere('c.close_date <=:close_date')
->setParameter('close_date', $request->get('close_date'));
}
$em->getQuery()->getArrayResult();
return new JsonResponse($em);
}
Notice how I have removed the semicolon from the following pieces of code:
if ($request->request->get('status')) {
$em->where('c.status = :status')
->setParameter('status', $request->request->get('status'));
};
if (strtoupper(trim($request->get('client')))) {
$em->andWhere('(d.name_fantasy=:client OR d.razao_social=:client)')
->setParameter('client', strtoupper(trim($request->get('client'))));
};
Also notice how I have change the JOIN:
->join('c.Clients', 'd', Join::ON, 'c.id_client = d.id');
UPDATE:
Change this:
if(strtoupper(trim($request->get('client')))) {
$client = strtoupper(trim($request->get('client')));
$em->andWhere('d.name_fantasy=:client')
->orWhere('d.razao_social=:client')
->setParameter('client', $client);
}
Or:
if (strtoupper(trim($request->get('client')))) {
$em->andWhere('d.name_fantasy=:client OR d.razao_social=:client')
->setParameter('client', strtoupper(trim($request->get('client'))));
};
More info here.

Type conversion error from LifecycleEventArgs

I have no idea for this. I'm a beginner of symfony3.
code
/**
* Set createdAt
* #ORM\PrePersist()
* #param \DateTime $createdAt
*
* #return Book
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Get createdAt
*
* #return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Set updateAt
*
* #param \DateTime $updateAt
*
* #return Book
*/
public function setUpdateAt($updateAt)
{
$this->updateAt = $updateAt;
return $this;
}
/**
* Get updateAt
*
* #return \DateTime
*/
public function getUpdateAt()
{
return $this->updateAt;
}
/**
* #ORM\PrePersist()
*/
public function PrePersist() {
if ($this->getCreatedAt() == null) {
$this->setCreatedAt(new \DateTime('now'));
}
$this->setUpdateAt(new \DateTime('now'));
}
/**
* #ORM\PreUpdate()
*/
public function PreUpdate() {
$this->setUpdateAt(new \DateTime('now'));
}
it gives an error report as below :
Error
Could not convert PHP value of type 'Doctrine\ORM\Event\LifecycleEventArgs' to type 'datetime'. Expected one of the following types: null, DateTime
Help me to figure it out.

Symfony2 onetoone relationship

I am developing an application using symfony2 and using orm.yml files to mapp the entities into the database. The problem comes when trying to create a relation for two entities that share a onetoone relationship (Markagarria.php and GalderaPaketea.php). When running php app/console doctrine:schema:update --force it shows the next message: Nothing to update - your database is already in sync with the current entity metadata.
This is the code for the entities:
<?php
namespace Anotatzailea\AnotatzaileaBundle\Entity;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Anotatzailea\AnotatzaileaBundle\Entity\Markagarria
*
* #ORM\Table(name="Markagarria")
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class Markagarria
{
/**
* #var integer $MarkId
*
* #ORM\Column(name="MarkId", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $MarkId;
/**
* #ORM\ManyToOne(targetEntity="Dokumentua", inversedBy="Markagarriak")
* #ORM\JoinColumn(name="DokId", referencedColumnName="DokId")
*/
protected $Dokumentua;
/**
* #ORM\oneToOne(targetEntity="GalderaPaketea", mappedBy="Markagarria")
*/
private $GalderaPaketea;
/**
* Get MarkId
*
* #return integer
*/
public function getMarkId()
{
return $this->MarkId;
}
/**
* Set GalderaPaketea
*
* #param Anotatzailea\AnotatzaileaBundle\Entity\GalderaPaketea $galderaPaketea
*/
public function setGalderaPaketea(\Anotatzailea\AnotatzaileaBundle\Entity\GalderaPaketea $galderaPaketea)
{
$this->GalderaPaketea = $galderaPaketea;
}
/**
* Get GalderaPaketea
*
* #return Anotatzailea\AnotatzaileaBundle\Entity\GalderaPaketea
*/
public function getGalderaPaketea()
{
return $this->GalderaPaketea;
}
/**
* Set Dokumentua
*
* #param Anotatzailea\AnotatzaileaBundle\Entity\Dokumentua $dokumentua
*/
public function setDokumentua(\Anotatzailea\AnotatzaileaBundle\Entity\Dokumentua $dokumentua)
{
$this->Dokumentua = $dokumentua;
}
/**
* Get Dokumentua
*
* #return Anotatzailea\AnotatzaileaBundle\Entity\Dokumentua
*/
public function getDokumentua()
{
return $this->Dokumentua;
}
}
<?php
namespace Anotatzailea\AnotatzaileaBundle\Entity;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Anotatzailea\AnotatzaileaBundle\Entity\GalderaPaketea
*
* #ORM\Table(name="GalderaPaketea")
* #ORM\Entity
*/
class GalderaPaketea
{
/**
* #var integer $GalPakId
*
* #ORM\Column(name="GalPakId", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $GalPakId;
/**
* #var integer $BalidatzeEginak
*
* #ORM\Column(name="BalidatzeEginak", type="integer")
*/
private $BalidatzeEginak;
/**
* #var integer $InterpretatzeEginak
*
* #ORM\Column(name="InterpretatzeEginak", type="integer")
*/
private $InterpretatzeEginak;
/**
* #var boolean $PaketeEgoera
*
* #ORM\Column(name="PaketeEgoera", type="boolean")
*/
private $PaketeEgoera;
/**
* #ORM\oneToOne(targetEntity="Markagarria", mappedBy="GalderaPaketea")
* #ORM\JoinColumn(name="MarkId", referencedColumnName="MarkId")
*/
private $Markagarria;
/**
* Get GalPakId
*
* #return integer
*/
public function getGalPakId()
{
return $this->GalPakId;
}
/**
* Set BalidatzeEginak
*
* #param integer $balidatzeEginak
*/
public function setBalidatzeEginak($balidatzeEginak)
{
$this->BalidatzeEginak = $balidatzeEginak;
}
/**
* Get BalidatzeEginak
*
* #return integer
*/
public function getBalidatzeEginak()
{
return $this->BalidatzeEginak;
}
/**
* Set InterpretatzeEginak
*
* #param integer $interpretatzeEginak
*/
public function setInterpretatzeEginak($interpretatzeEginak)
{
$this->InterpretatzeEginak = $interpretatzeEginak;
}
/**
* Get InterpretatzeEginak
*
* #return integer
*/
public function getInterpretatzeEginak()
{
return $this->InterpretatzeEginak;
}
/**
* Set PaketeEgoera
*
* #param boolean $paketeEgoera
*/
public function setPaketeEgoera($paketeEgoera)
{
$this->PaketeEgoera = $paketeEgoera;
}
/**
* Get PaketeEgoera
*
* #return boolean
*/
public function getPaketeEgoera()
{
return $this->PaketeEgoera;
}
/**
* Set Markagarria
*
* #param Anotatzailea\AnotatzaileaBundle\Entity\Markagarria $markagarria
*/
public function setMarkagarria(\Anotatzailea\AnotatzaileaBundle\Entity\Markagarria $markagarria)
{
$this->Markagarria = $markagarria;
}
/**
* Get Markagarria
*
* #return Anotatzailea\AnotatzaileaBundle\Entity\Markagarria
*/
public function getMarkagarria()
{
return $this->Markagarria;
}
}
And the orm.yml files have the following content:
Anotatzailea\AnotatzaileaBundle\Entity\Markagarria:
type: entity
table: Markagarria
fields:
MarkId:
type: integer
id: true
precision: 0
scale: 0
unique: false
nullable: false
generator:
strategy: IDENTITY
manyToOne:
Dokumentua:
targetEntity: Anotatzailea\AnotatzaileaBundle\Entity\Dokumentua
cascade: { }
mappedBy: null
inversedBy: Markagarriak
joinColumns:
DokId:
referencedColumnName: DokId
orphanRemoval: false
oneToOne:
GalderaPaketea:
targetEntity: Anotatzailea\AnotatzaileaBundle\Entity\GalderaPaketea
cascade: { }
mappedBy: Markagarria
lifecycleCallbacks: { }
Anotatzailea\AnotatzaileaBundle\Entity\GalderaPaketea:
type: entity
table: GalderaPaketea
fields:
GalPakId:
type: integer
id: true
precision: 0
scale: 0
unique: false
nullable: false
generator:
strategy: IDENTITY
BalidatzeEginak:
type: integer
precision: 0
scale: 0
unique: false
nullable: false
InterpretatzeEginak:
type: integer
precision: 0
scale: 0
unique: false
nullable: false
PaketeEgoera:
type: boolean
precision: 0
scale: 0
unique: false
nullable: false
oneToOne:
Markagarria:
targetEntity: Anotatzailea\AnotatzaileaBundle\Entity\Markagarria
cascade: { }
mappedBy: GalderaPaketea
joinColumn:
name: MarkId
referencedColumnName: MarkId
lifecycleCallbacks: { }
It looks like your entry in the the entity GalderaPaketea should be:
/**
* #ORM\oneToOne(targetEntity="Markagarria", inversedBy="GalderaPaketea")
* #ORM\JoinColumn(name="MarkId", referencedColumnName="MarkId")
*/
Neither entity is claiming ownership so no db update is performed.
Check out Doctrine Association mappings - OneToOne Bi-directional
I'm new to Symfony myself and I found this document very helpful.

Symfony2 mapping onetomany manytone

I am developing an application using symfony2 and using orm.yml files for mapping the entities into the database. The problem comes when trying to create the database tables for two entities that share a onetomany relationship (Anotatzea.php and Dokumentua.php). When running php app/console doctrine:schema:update --force it shows the next error
[RuntimeException]
The autoloader expected class "Anotatzailea\AnotatzaileaBundle\Entity\Anotatzea" to be defined in file "/var/www/Symfony/app/../src/Anotatzailea/AnotatzaileaBundle/Entity/Anotatzea.php". The file was found but the class was not in it, the class name or namespace probably has a typo.
The entities have the following code:
<?php
namespace Anotatzailea\AnotatzaileaBundle\Entity;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Anotatzailea\AnotatzaileaBundle\Entity\Dokumentua
*
* #ORM\Table(name="Dokumentua")
* #ORM\Entity
*/
class Dokumentua
{
/**
* #var integer $DokId
*
* #ORM\Column(name="DokId", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $DokId;
/**
* #var string $Izenburua
*
* #ORM\Column(name="Izenburua", type="string", length=30)
*/
private $Izenburua;
/**
* #var string $Egilea
*
* #ORM\Column(name="Egilea", type="string", length=40)
*/
private $Egilea;
/**
* #var date $ErregistroData
*
* #ORM\Column(name="ErregistroData", type="date")
*/
private $ErregistroData;
/**
* #var boolean $DokEgoera
*
* #ORM\Column(name="DokEgoera", type="boolean")
*/
private $DokEgoera;
/**
* #ORM\OneToMany(targetEntity="Anotatzea", mappedBy="Dokumentua")
*/
protected $Anotatzeak;
/**
* Get DokId
*
* #return integer
*/
public function getDokId()
{
return $this->DokId;
}
/**
* Set Izenburua
*
* #param string $izenburua
*/
public function setIzenburua($izenburua)
{
$this->Izenburua = $izenburua;
}
/**
* Get Izenburua
*
* #return string
*/
public function getIzenburua()
{
return $this->Izenburua;
}
/**
* Set Egilea
*
* #param string $egilea
*/
public function setEgilea($egilea)
{
$this->Egilea = $egilea;
}
/**
* Get Egilea
*
* #return string
*/
public function getEgilea()
{
return $this->Egilea;
}
/**
* Set ErregistroData
*
* #param date $erregistroData
*/
public function setErregistroData($erregistroData)
{
$this->ErregistroData = $erregistroData;
}
/**
* Get ErregistroData
*
* #return date
*/
public function getErregistroData()
{
return $this->ErregistroData;
}
/**
* Set DokEgoera
*
* #param boolean $dokEgoera
*/
public function setDokEgoera($dokEgoera)
{
$this->DokEgoera = $dokEgoera;
}
/**
* Get DokEgoera
*
* #return boolean
*/
public function getDokEgoera()
{
return $this->DokEgoera;
}
public function __construct()
{
$this->Anotatzeak = new ArrayCollection();
}
}
<?php
namespace Anotatzailea\AnotatzaileaBundle\Anotatzea;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Anotatzailea\AnotatzaileaBundle\Entity\Anotatzea
*
* #ORM\Table(name="Anotatzea")
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class Anotatzea
{
/**
* #var integer $AnotId
*
* #ORM\Column(name="AnotId", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $AnotId;
/**
* #ORM\ManyToOne(targetEntity="Dokumentua", inversedBy="Anotatzeak")
* #ORM\JoinColumn(name="DokId", referencedColumnName="DokId")
*/
protected $Dokumentua;
/**
* Get AnotId
*
* #return integer
*/
public function getAnotId()
{
return $this->AnotId;
}
/**
* Set Dokumentua
*
* #param Anotatzailea\AnotatzaileaBundle\Entity\Dokumentua $dokumentua
*/
public function setDokumentua(\Anotatzailea\AnotatzaileaBundle\Entity\Dokumentua $dokumentua)
{
$this->Dokumentua = $dokumentua;
}
/**
* Get Dokumentua
*
* #return Anotatzailea\AnotatzaileaBundle\Entity\Dokumentua
*/
public function getDokumentua()
{
return $this->Dokumentua;
}
/**
* #ORM\prePersist
*/
public function setUpdatedValue()
{
// Add your code here
}
}
And the orm.yml files:
Anotatzailea\AnotatzaileaBundle\Entity\Dokumentua:
type: entity
table: Dokumentua
fields:
DokId:
type: integer
id: true
precision: 0
scale: 0
unique: false
nullable: false
generator:
strategy: IDENTITY
Izenburua:
type: string
length: 30
precision: 0
scale: 0
unique: false
nullable: false
Egilea:
type: string
length: 40
precision: 0
scale: 0
unique: false
nullable: false
ErregistroData:
type: date
precision: 0
scale: 0
unique: false
nullable: false
DokEgoera:
type: boolean
precision: 0
scale: 0
unique: false
nullable: false
OneToMany:
Anotatzeak:
targetEntity: Anotatzailea\AnotatzaileaBundle\Entity\Anotatzea
cascade: { }
mappedBy: Dokumentua
inversedBy: null
orphanRemoval: false
cascade: ["persist", "merge","remove"]
orderBy: null
lifecycleCallbacks: { }
Anotatzailea\AnotatzaileaBundle\Entity\Anotatzea:
type: entity
table: Anotatzea
fields:
AnotId:
type: integer
id: true
precision: 0
scale: 0
unique: false
nullable: false
generator:
strategy: IDENTITY
manyToOne:
Dokumentua:
targetEntity: Anotatzailea\AnotatzaileaBundle\Entity\Dokumentua
cascade: { }
mappedBy: null
inversedBy: Anotatzeak
joinColumns:
DokId:
referencedColumnName: DokId
orphanRemoval: false
lifecycleCallbacks: { }
The namespace name in the second entity file is wrong.
Replace:
namespace Anotatzailea\AnotatzaileaBundle\Anotatzea;
with:
namespace Anotatzailea\AnotatzaileaBundle\Entity;