Doctrine: ManyToMany matching criteria set wrong expressions - symfony

I have two entities: User and Event, they are in ManyToMany relationship.
I try to match events by criteria from $user->getEvents() but get nothing. After checking profiler i saw that criteria did not work correctly while build sql, i used expression lte and gte but in sql doctrine continue to use =.
Here are my classes.
User:
<?php
namespace App\UserBundle\Entity;
use App\CoreBundle\Entity\Event;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use JMS\Serializer\Annotation as JMS;
/**
* #JMS\ExclusionPolicy("all")
*
* #ORM\Entity(repositoryClass="App\UserBundle\Repository\UserRepository")
* #ORM\Table(name="users", uniqueConstraints={#ORM\UniqueConstraint(name="User",columns={"login", "email"})})
* #UniqueEntity(fields={"login","email"})
* #ORM\HasLifecycleCallbacks()
*/
class User
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="login", type="string", length=255, unique=true, nullable=false)
* #Assert\NotBlank()
*/
protected $login;
/**
* #JMS\Expose
*
* #ORM\Column(name="name", type="string", length=255, unique=true, nullable=false)
* #Assert\NotBlank()
*/
protected $name;
/**
* #JMS\Expose
*
* #ORM\Column(name="email", type="string", length=255, unique=true, nullable=false)
* #Assert\NotBlank()
*/
protected $email;
/**
* #ORM\Column(name="roles", type="array", nullable=false)
* #Assert\NotBlank()
*/
protected $roles;
/**
* #ORM\Column(name="blocked", type="boolean")
* #Assert\NotBlank()
*/
protected $blocked;
/**
* #ORM\Column(type="datetime")
*/
protected $created;
/**
* #ORM\Column(type="datetime")
*/
protected $updated;
/**
* #ORM\ManyToMany(targetEntity="App\CoreBundle\Entity\Event", inversedBy="users", cascade={"persist", "remove"})
* #ORM\JoinTable(name="users_events",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="cascade")},
* inverseJoinColumns={#ORM\JoinColumn(name="event_id", referencedColumnName="id", onDelete="cascade")}
* )
*/
protected $events;
public function __construct()
{
$this->roles = array();
$this->events = new ArrayCollection();
$this->setCreated(new \DateTime());
$this->setUpdated(new \DateTime());
}
public function __toString()
{
return (string) $this->id;
}
/**
* #ORM\PreUpdate
*/
public function setUpdatedValue()
{
$this->setUpdated(new \DateTime());
}
/**
* Set created.
*
* #param \DateTime $created
*
* #return User
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created.
*
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set updated.
*
* #param \DateTime $updated
*
* #return User
*/
public function setUpdated($updated)
{
$this->updated = $updated;
return $this;
}
/**
* Get updated.
*
* #return \DateTime
*/
public function getUpdated()
{
return $this->updated;
}
public function getId()
{
return $this->id;
}
/**
* Get Login.
*
* #return string
*/
public function getLogin()
{
return $this->login;
}
/**
* Set Login.
*
* #param $login
*
* #return User
*/
public function setLogin($login)
{
$this->login = $login;
return $this;
}
/**
* Get Name.
*
* #return mixed
*/
public function getName()
{
return $this->name;
}
/**
* Set Name.
*
* #param string $name
*
* #return User
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get Email.
*
* #return mixed
*/
public function getEmail()
{
return $this->email;
}
/**
* Set Email.
*
* #param mixed $email
*
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get roles.
*
* #return mixed
*/
public function getRoles()
{
return $this->roles;
}
/**
* Set Roles.
*
* #param mixed $roles
*
* #return User
*/
public function setRoles($roles)
{
$this->roles = array();
foreach ($roles as $role) {
$this->addRole($role);
}
return $this;
}
/**
* Add role to collection.
*
* #param $role
*
* #return User
*/
public function addRole($role)
{
$role = strtoupper($role);
if (!in_array($role, $this->roles, true)) {
$this->roles[] = $role;
}
return $this;
}
/**
* Get Blocked.
*
* #return boolean
*/
public function getBlocked()
{
return $this->blocked;
}
/**
* Set Blocked.
*
* #param boolean $blocked
*
* #return User
*/
public function setBlocked($blocked)
{
$this->blocked = $blocked;
return $this;
}
/**
* Add event.
*
* #param Event $event
*
* #return User
*/
public function addEvent(Event $event)
{
if (!$this->events->contains($event)) {
$this->events[] = $event;
}
return $this;
}
/**
* Remove event.
*
* #param Event $event
*
* #return User
*/
public function removeEvent(Event $event)
{
if ($this->events->contains($event)) {
$this->events->removeElement($event);
}
return $this;
}
/**
* Get events.
*
* #return ArrayCollection
*/
public function getEvents()
{
return $this->events;
}
}
Event:
<?php
namespace App\CoreBundle\Entity;
use App\UserBundle\Entity\User;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Event
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="App\CoreBundle\Repository\EventRepository")
*/
class Event
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="event_name", type="string", length=50)
*/
private $eventName;
/**
* #var string
*
* #ORM\Column(name="event_description", type="string", length=160)
*/
private $eventDescription;
/**
* #var string
*
* #ORM\Column(name="event_type", type="string", length=100)
*/
private $eventType;
/**
* #var boolean
*
* #ORM\Column(name="visible", type="boolean")
*/
private $visible;
/**
* #var \DateTime
*
* #ORM\Column(name="start_date", type="datetime")
*/
private $startDate;
/**
* #var \DateTime
*
* #ORM\Column(name="end_date", type="datetime")
*/
private $endDate;
/**
* #ORM\ManyToMany(targetEntity="App\UserBundle\Entity\User", mappedBy="events")
*/
protected $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set eventName
*
* #param string $eventName
* #return Event
*/
public function setEventName($eventName)
{
$this->eventName = $eventName;
return $this;
}
/**
* Get eventName
*
* #return string
*/
public function getEventName()
{
return $this->eventName;
}
/**
* Set eventDescription
*
* #param string $eventDescription
* #return Event
*/
public function setEventDescription($eventDescription)
{
$this->eventDescription = $eventDescription;
return $this;
}
/**
* Get eventDescription
*
* #return string
*/
public function getEventDescription()
{
return $this->eventDescription;
}
/**
* Set eventType
*
* #param string $eventType
* #return Event
*/
public function setEventType($eventType)
{
$this->eventType = $eventType;
return $this;
}
/**
* Get eventType
*
* #return string
*/
public function getEventType()
{
return $this->eventType;
}
/**
* Set visible
*
* #param boolean $visible
* #return Event
*/
public function setVisible($visible)
{
$this->visible = $visible;
return $this;
}
/**
* Get visible
*
* #return boolean
*/
public function getVisible()
{
return $this->visible;
}
/**
* Set startDate
*
* #param \DateTime $startDate
* #return Event
*/
public function setStartDate($startDate)
{
$this->startDate = $startDate;
return $this;
}
/**
* Get startDate
*
* #return \DateTime
*/
public function getStartDate()
{
return $this->startDate;
}
/**
* Set endDate
*
* #param \DateTime $endDate
* #return Event
*/
public function setEndDate($endDate)
{
$this->endDate = $endDate;
return $this;
}
/**
* Get endData
*
* #return \DateTime
*/
public function getEndDate()
{
return $this->endDate;
}
/**
* Set users.
*
* #param ArrayCollection $users
*
* #return Event
*/
public function setUsers(ArrayCollection $users)
{
$this->users = $users;
return $this;
}
/**
* Add user.
*
* #param User $user
*
* #return Event
*/
public function addUser(User $user)
{
if (!$this->users->contains($user)) {
$this->users[] = $user;
}
return $this;
}
/**
* Get user.
*
* #return User
*/
public function getUsers()
{
return $this->users;
}
/**
* Remove user
*
* #param User $user
*/
public function removeUser(User $user)
{
$this->users->removeElement($user);
}
}
And here is how i try to find events related to user:
private function getActiveEventsCriteria($camelStyle = true, $dateAsObject = true)
{
$currentDateTime = new \DateTime();
$criteria = Criteria::create()
->where(
Criteria::expr()->andX(
Criteria::expr()->lte($camelStyle ? 'startDate' : 'start_date', $dateAsObject ? $currentDateTime : $currentDateTime->format("Y-m-d H:i:s")),
Criteria::expr()->gte($camelStyle ? 'endDate' : 'end_date', $dateAsObject ? $currentDateTime : $currentDateTime->format("Y-m-d H:i:s"))
)
)
->andWhere(Criteria::expr()->eq('visible', 1));
return $criteria;
}
public function getParticipatingEventsBy(User $user)
{
$userEvents = $user->getEvents();
if (is_null($userEvents)) return [];
return $userEvents->matching($this->getActiveEventsCriteria(false, false));
}
$this->getParticipatingEventsBy($user);
In profiler/debug i see next sql:
SELECT
te.id AS id,
te.event_name AS event_name,
te.event_description AS event_description,
te.event_type AS event_type,
te.visible AS visible,
te.start_date AS start_date,
te.end_date AS end_date
FROM
event te
JOIN users_events t ON t.event_id = te.id
WHERE
t.user_id = ?
AND te.start_date = ?
AND te.end_date = ?
AND te.visible = ?
And with applied parameters:
SELECT
te.id AS id,
te.event_name AS event_name,
te.event_description AS event_description,
te.event_type AS event_type,
te.visible AS visible,
te.start_date AS start_date,
te.end_date AS end_date
FROM
event te
JOIN users_events t ON t.event_id = te.id
WHERE
t.user_id = 14 AND
te.start_date = '2015-12-03 16:26:44' AND
te.end_date = '2015-12-03 16:26:44' AND
te.visible = 1;
I changed WHERE to next:
WHERE
t.user_id = 14 AND
te.start_date <= '2015-12-03 16:26:44' AND
te.end_date >= '2015-12-03 16:26:44' AND
te.visible = 1;
And with that sql i got correct result.
When i use same criteria right with repository without relation to user - everything is ok:
public function getActiveEvents() {
return $this->matching($this->getActiveEventsCriteria());
}
public function matching(Criteria $criteria)
{
return $this->repository->matching($criteria);
}
$this->getActiveEvents();
This is formatted sql:
SELECT
t0.id AS id_1,
t0.event_name AS event_name_2,
t0.event_description AS event_description_3,
t0.event_type AS event_type_4,
t0.visible AS visible_5,
t0.start_date AS start_date_6,
t0.end_date AS end_date_7
FROM
event t0
WHERE
(
(
t0.start_date <= ?
AND t0.end_date >= ?
)
AND t0.visible = ?
)
And with applied parameters:
SELECT
t0.id AS id_1,
t0.event_name AS event_name_2,
t0.event_description AS event_description_3,
t0.event_type AS event_type_4,
t0.visible AS visible_5,
t0.start_date AS start_date_6,
t0.end_date AS end_date_7
FROM
event t0
WHERE
((t0.start_date <= '2015-12-03 17:01:47' AND t0.end_date >= '2015-12-03 17:01:47') AND
t0.visible = 1);
As you can see, for case when i dont try to search through relation - everything is ok, i get result. But when i try related events to user with use of Criteria - it fails and return empty result cause of incorrect sql.
I use php 5.6.*, symfony 2.8, doctrine 2.5.2, latest MySQL.
Any help will be very appreciated.
Thank you.
UPDATE:
- created issue in JIRA: here

Related

Using findBy return empty array collection

I need to find a single row from the database and I am using findOneBy().
findBy() and findOneBy() and any other symfony functions always return an empty array collection for my ManyToOne related entities when I loop through the collection.
But when using findAll() function and I loop through the collection, it returns the expected data.
You will find the controller function at the end of the question with the different find functions I have used and do not work.
Entities listed below:
The news entity is related to the newsBlocks entity and newsBlocks is related to the legalNotices entity.
They all are related by ManyToOne/OneToMany relationship.
News Entity
<?php
namespace Honda\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
/**
* News
*
* #ORM\Table(name="news")
* #ORM\Entity(repositoryClass="Honda\MainBundle\Repository\NewsRepository")
*/
class News
{
use Traits\DistributorTrait,
Traits\StartDateEndDateTrait,
Traits\HomeActivationTrait,
Traits\ActivationTrait,
Traits\RedirectionTrait;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #Assert\NotBlank()
* #ORM\Column(name="title", type="string", length=255, nullable=true)
*/
private $title;
/**
* #var string
*
* #Assert\NotBlank()
* #ORM\Column(name="description1", type="text", nullable=true)
*/
private $description1;
/**
* #var integer
*
* #ORM\Column(name="type", type="integer", nullable=true)
*/
private $type;
/**
* #Gedmo\Slug(fields={"title"})
* #ORM\Column(unique=true)
*/
private $slug;
/**
*
* #ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media", cascade={"all"}, fetch="LAZY")
* #ORM\JoinColumn(name="image", referencedColumnName="id", onDelete="SET NULL", nullable=true)
*/
protected $image;
/**
*
* #ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media", cascade={"all"}, fetch="LAZY")
* #ORM\JoinColumn(name="image_mobile", referencedColumnName="id", onDelete="SET NULL", nullable=true)
*/
protected $image_mobile;
/**
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime", nullable=true)
*/
protected $createdAt;
/**
* #Gedmo\SortablePosition
* #ORM\Column(name="position", type="integer")
*/
private $position;
/**
* #ORM\OneToMany(targetEntity="Honda\MainBundle\Entity\NewsBlocks", mappedBy="news", cascade={"persist"})
*/
private $newsBlocks;
/**
* Constructor.
*/
public function __construct()
{
$this->createdAt = new \DateTime('NOW', new \DateTimeZone('Europe/Paris'));
$this->slides = new ArrayCollection();
$this->newsBlocks = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #return string
*/
public function __toString()
{
if ($this->getId()) {
return $this->getTitle();
}
return '';
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
*
* #return News
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set description1
*
* #param string $description1
*
* #return News
*/
public function setDescription1($description1)
{
$this->description1 = $description1;
return $this;
}
/**
* Get description1
*
* #return string
*/
public function getDescription1()
{
return $this->description1;
}
/**
* Set type
*
* #param integer $type
*
* #return News
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* Get type
*
* #return integer
*/
public function getType()
{
return $this->type;
}
/**
* Set image
*
* #param \Application\Sonata\MediaBundle\Entity\Media $image
*
* #return News
*/
public function setImage(\Application\Sonata\MediaBundle\Entity\Media $image = null)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return \Application\Sonata\MediaBundle\Entity\Media
*/
public function getImage()
{
return $this->image;
}
/**
* Set slug
*
* #param string $slug
*
* #return News
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* Set createdAt
*
* #param \DateTime $createdAt
* #return News
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Get createdAt
*
* #return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Set position
*
* #param integer $position
*
* #return ALaUne
*/
public function setPosition($position)
{
$this->position = $position;
return $this;
}
/**
* Get position
*
* #return integer
*/
public function getPosition()
{
return $this->position;
}
/**
* Set imageMobile.
*
* #param \Application\Sonata\MediaBundle\Entity\Media|null $imageMobile
*
* #return News
*/
public function setImageMobile(\Application\Sonata\MediaBundle\Entity\Media $imageMobile = null)
{
$this->image_mobile = $imageMobile;
return $this;
}
/**
* Get imageMobile.
*
* #return \Application\Sonata\MediaBundle\Entity\Media|null
*/
public function getImageMobile()
{
return $this->image_mobile;
}
/**
* Add newsBlock.
*
* #param \Honda\MainBundle\Entity\NewsBlocks $newsBlock
*
* #return NewNews
*/
public function addNewsBlock(\Honda\MainBundle\Entity\NewsBlocks $newsBlock)
{
if (!$this->newsBlocks->contains($newsBlock)) {
$this->newsBlocks[] = $newsBlock;
$newsBlock->setNews($this);
}
return $this;
}
/**
* Remove newsBlock.
*
* #param \Honda\MainBundle\Entity\NewsBlocks $newsBlock
*
* #return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
public function removeNewsBlock(\Honda\MainBundle\Entity\NewsBlocks $newsBlock)
{
if (!$this->newsBlocks->contains($newsBlock)) {
return;
}
$this->newsBlocks->removeElement($newsBlock);
$newsBlock->setNews(null);
return $this;
}
/**
* Get newsBlocks.
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getNewsBlocks()
{
return $this->newsBlocks;
}
}
NewsBlocks
<?php
namespace Honda\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Honda\MainBundle\Entity\Traits;
use Doctrine\Common\Collections\ArrayCollection;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* NewsBlocks
*
* #ORM\Table(name="news_blocks")
* #ORM\Entity(repositoryClass="Honda\MainBundle\Repository\NewsBlocksRepository")
*/
class NewsBlocks
{
use Traits\DistributorTrait;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="block_name", type="string", length=255)
*/
private $blockName;
/**
* #ORM\OneToMany(targetEntity="Honda\MainBundle\Entity\News\Offer", mappedBy="newsBlockOffer", cascade={"all"})
*/
private $offers;
/**
* #ORM\OneToMany(targetEntity="Honda\MainBundle\Entity\News\Video", mappedBy="newsBlockVideo", cascade={"persist"})
*/
private $videos;
/**
* #ORM\OneToMany(targetEntity="Honda\MainBundle\Entity\News\LegalNotices", mappedBy="newsBlockLegalNotices", cascade={"persist"})
*/
private $legalNotices;
/**
* #ORM\OneToMany(targetEntity="Honda\MainBundle\Entity\News\OfferCarousel", mappedBy="newsOfferBlocks", cascade={"persist"})
*/
private $offerCarousels;
/**
* #ORM\ManyToOne(targetEntity="Honda\MainBundle\Entity\News", inversedBy="newsBlocks", cascade={"persist"})
*/
private $news;
/**
* #ORM\OneToMany(targetEntity="Honda\MainBundle\Entity\News\PhotoSlider", mappedBy="newsPhotoSliderBlock", cascade={"persist"})
*/
private $photoSliders;
/**
* #ORM\Column(name="position", type="integer")
*/
private $position;
/**
* Get id.
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Constructor
*/
public function __construct()
{
$this->offers = new \Doctrine\Common\Collections\ArrayCollection();
$this->videos = new \Doctrine\Common\Collections\ArrayCollection();
$this->legalNotices = new \Doctrine\Common\Collections\ArrayCollection();
$this->offerCarousels = new \Doctrine\Common\Collections\ArrayCollection();
$this->photoSliders = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add offer.
*
* #param \Honda\MainBundle\Entity\News\Offer $offer
*
* #return NewsBlocks
*/
public function addOffer(\Honda\MainBundle\Entity\News\Offer $offer)
{
if (!$this->offers->contains($offer)) {
$this->offers[] = $offer;
$offer->setNewsBlockOffer($this);
}
return $this;
}
/**
* Remove offer.
*
* #param \Honda\MainBundle\Entity\News\Offer $offer
*
* #return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
public function removeOffer(\Honda\MainBundle\Entity\News\Offer $offer)
{
if (!$this->offers->contains($offer)) {
return;
}
$this->offers->removeElement($offer);
$offer->setNewsBlockOffers(null);
return $this;
}
/**
* Get offers.
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getOffers()
{
return $this->offers;
}
/**
* Add video.
*
* #param \Honda\MainBundle\Entity\News\Video $video
*
* #return NewsBlocks
*/
public function addVideo(\Honda\MainBundle\Entity\News\Video $video)
{
if (!$this->videos->contains($video)) {
$this->videos[] = $video;
$video->setNewsBlockVideo($this);
}
return $this;
}
/**
* Remove video.
*
* #param \Honda\MainBundle\Entity\News\Video $video
*
* #return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
public function removeVideo(\Honda\MainBundle\Entity\News\Video $video)
{
if (!$this->videos->contains($video)) {
return;
}
$this->videos->removeElement($video);
$video->setNewsBlockVideo(null);
return $this;
}
/**
* Get videos.
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getVideos()
{
return $this->videos;
}
/**
* Set blockName.
*
* #param string $blockName
*
* #return NewsBlocks
*/
public function setBlockName($blockName)
{
$this->blockName = $blockName;
return $this;
}
/**
* Get blockName.
*
* #return string
*/
public function getBlockName()
{
return $this->blockName;
}
/**
* Add legalNotice.
*
* #param \Honda\MainBundle\Entity\News\LegalNotices $legalNotice
*
* #return NewsBlocks
*/
public function addLegalNotice(\Honda\MainBundle\Entity\News\LegalNotices $legalNotice)
{
if (!$this->legalNotices->contains($legalNotice)) {
$this->legalNotices[] = $legalNotice;
$legalNotice->setNewsBlockLegalNotices($this);
}
return $this;
}
/**
* Remove legalNotice.
*
* #param \Honda\MainBundle\Entity\News\LegalNotices $legalNotice
*
* #return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
public function removeLegalNotice(\Honda\MainBundle\Entity\News\LegalNotices $legalNotice)
{
if (!$this->legalNotices->contains($legalNotice)) {
return;
}
$this->legalNotices->removeElement($legalNotice);
$legalNotice->setUniqueLook(null);
return $this;
}
/**
* Get legalNotices.
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getLegalNotices()
{
return $this->legalNotices;
}
/**
* Add offerCarousel.
*
* #param \Honda\MainBundle\Entity\News\OfferCarousel $offerCarousel
*
* #return NewsBlocks
*/
public function addOfferCarousel(\Honda\MainBundle\Entity\News\OfferCarousel $offerCarousel)
{
if (!$this->offerCarousels->contains($offerCarousel)) {
$this->offerCarousels[] = $offerCarousel;
$offerCarousel->setNewsOfferBlocks($this);
}
return $this;
}
/**
* Remove offerCarousel.
*
* #param \Honda\MainBundle\Entity\News\OfferCarousel $offerCarousel
*
* #return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
public function removeOfferCarousel(\Honda\MainBundle\Entity\News\OfferCarousel $offerCarousel)
{
if (!$this->offerCarousels->contains($offerCarousel)) {
return;
}
$this->offerCarousels->removeElement($offerCarousel);
$offerCarousel->setNewsOfferBlocks(null);
return $this;
}
/**
* Get offerCarousels.
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getOfferCarousels()
{
return $this->offerCarousels;
}
/**
* Set news.
*
* #param \Honda\MainBundle\Entity\News|null $news
*
* #return NewsBlocks
*/
public function setNews(\Honda\MainBundle\Entity\News $news = null)
{
$this->news = $news;
return $this;
}
/**
* Get news.
*
* #return \Honda\MainBundle\Entity\News|null
*/
public function getNews()
{
return $this->news;
}
/**
* Add photoSlider.
*
* #param \Honda\MainBundle\Entity\News\PhotoSlider $photoSlider
*
* #return NewsBlocks
*/
public function addPhotoSlider(\Honda\MainBundle\Entity\News\PhotoSlider $photoSlider)
{
if (!$this->photoSliders->contains($photoSlider)) {
$this->photoSliders[] = $photoSlider;
$photoSlider->setNewsPhotoSliderBlock($this);
}
return $this;
}
/**
* Remove photoSlider.
*
* #param \Honda\MainBundle\Entity\News\PhotoSlider $photoSlider
*
* #return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
public function removePhotoSlider(\Honda\MainBundle\Entity\News\PhotoSlider $photoSlider)
{
if (!$this->photoSliders->contains($photoSlider)) {
return;
}
$this->photoSliders->removeElement($photoSlider);
$photoSlider->setNewsPhotoSliderBlock(null);
}
/**
* Get slides.
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getPhotoSliders()
{
return $this->photoSliders;
}
/**
* Set position.
*
* #param int $position
*
* #return NewsBlocks
*/
public function setPosition($position)
{
$this->position = $position;
return $this;
}
/**
* Get position.
*
* #return int
*/
public function getPosition()
{
return $this->position;
}
}
Legal Notices
<?php
namespace Honda\MainBundle\Entity\News;
use Doctrine\ORM\Mapping as ORM;
use Honda\MainBundle\Entity\Traits;
/**
* LegalNotices
*
* #ORM\Table(name="news_legal_notices")
* #ORM\Entity(repositoryClass="Honda\MainBundle\Repository\News\LegalNoticesRepository")
*/
class LegalNotices
{
use Traits\DistributorTrait,
Traits\ActivationTrait;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="description", type="text")
*/
private $description;
/**
* #ORM\ManyToOne(targetEntity="Honda\MainBundle\Entity\NewsBlocks", inversedBy="legalNotices", cascade={"persist"})
*/
private $newsBlockLegalNotices;
/**
* Get id.
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set description.
*
* #param string $description
*
* #return LegalNotices
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description.
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set newsBlockLegalNotices.
*
* #param \Honda\MainBundle\Entity\NewsBlocks|null $newsBlockLegalNotices
*
* #return LegalNotices
*/
public function setNewsBlockLegalNotices(\Honda\MainBundle\Entity\NewsBlocks $newsBlockLegalNotices = null)
{
$this->newsBlockLegalNotices = $newsBlockLegalNotices;
return $this;
}
/**
* Get newsBlockLegalNotices.
*
* #return \Honda\MainBundle\Entity\NewsBlocks|null
*/
public function getNewsBlockLegalNotices()
{
return $this->newsBlockLegalNotices;
}
}
Here is my function in the controller:
/**
* #Route("/actualites/{slug}", name="news_show_article", requirements={"slug": "[a-zA-Z0-9\-]+"})
*/
public function articleAction(Request $request, $slug)
{
$em = $this->getDoctrine()->getManager();
$news = $em->getRepository(News::class)->findBy(['slug' => $slug]); // Return specific row but collection emtpy
$news = $em->getRepository(News::class)->findOneBy(['slug' => $slug]); // Return specific row but collection emtpy
$news = $em->getRepository(News::class)->findBy([], ['createdAt' => 'DESC']); // Return all but collection empty
$r = $news[16]->getNewsBlocks();
foreach ($r as $item) {
dump($item);
}
$news = $em->getRepository(News::class)->findAll(); // Return all and collection is not emtpy
$r = $news[16]->getNewsBlocks();
foreach ($r as $item) {
foreach($item->getOffers() as $offer) {
dump($offer);
}
}
}

Foreign Key (don't want to edit it) error

I have a little problem i don't know why i can't edit my foreign key ($idProfile) but i can edit an other value from the database :
I can change the value enable for exemple but not the idProfile when i try to change it i have this error : "An instance of Symfony\Bundle\FrameworkBundle\Templating\EngineInterface must be injected in FOS\RestBundle\View\ViewHandler to render templates." don't know if that can help thx for help guys :p
my Profile controller :
/**
* Creates a new profile entity.
*
* #Route("/new/{id}", name="profile_new")
*/
public function newProfileAction(Request $request, User $user)
{
$loggedAs = $this->getUser();
$username = $loggedAs->getUsername();
$profile = new Profile();
$form = $this->createForm(ProfileType::class, $profile);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$profile->setLastConnexion(new \DateTime('now'));
$profile->setCreatedAccount(new \DateTime('now'));
$em = $this->getDoctrine()->getManager();
$em->persist($profile);
$em->flush();
$user->setEnabled('1');
$user->setIdLocation($profile->getId());
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
return $this->redirectToRoute('user_list');
}
return $this->render('admin/user/new_profile.html.twig', array(
'profile' => $profile,
'form' => $form->createView(),
'username' => $username,
));
}
My userEntity :
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
/**
* User
*
* #ORM\Table(name="user", uniqueConstraints=
{#ORM\UniqueConstraint(name="user_id_uindex", columns={"id"}),
#ORM\UniqueConstraint(name="user_username_uindex", columns=
{"username"})}, indexes={#ORM\Index(name="user_profile_id_fk",
columns={"id_profile"}), #ORM\Index(name="user_localisation_id_fk",
columns={"id_location"})})
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* #UniqueEntity("username", groups={"Default", "Patch"})
*/
class User implements UserInterface
{
const ROLE_USER = 'ROLE_USER';
const ROLE_ADMIN = 'ROLE_ADMIN';
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #Serializer\Groups({"Default", "Deserialize", "user_detail"})
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="username", type="string", length=32)
* #Serializer\Groups({"Default", "Deserialize", "user_detail"})
*/
protected $username;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255)
* #Serializer\Groups({"Deserialize", "user_detail"})
* #Assert\Regex(
* pattern="/(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).{7,}/",
* message="Password must be seven characters long and contain at least one digit code, upper case, and lower case letter!",
* groups={"Default", "Patch"}
* )
*/
protected $password;
/**
* #var boolean
*
* #ORM\Column(name="enabled", type="boolean", nullable=false)
*/
protected $enabled = '1';
/**
* #var \AppBundle\Entity\Localisation
*
* #ORM\ManyToOne(targetEntity="Localisation")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_location", referencedColumnName="id")
* })
*/
protected $idLocation;
/**
* #var \AppBundle\Entity\Profile
*
* #ORM\ManyToOne(targetEntity="Profile")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_profile", referencedColumnName="id")
* })
*/
protected $idProfile;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="User", inversedBy="idUserOne")
* #ORM\JoinTable(name="friend",
* joinColumns={
* #ORM\JoinColumn(name="id_user_one", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="id_user_two", referencedColumnName="id")
* }
* )
*/
protected $idUserTwo;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Place", inversedBy="idUserInvited")
* #ORM\JoinTable(name="list_invited",
* joinColumns={
* #ORM\JoinColumn(name="id_user_invited", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="id_place_invited", referencedColumnName="id")
* }
* )
*/
protected $idPlaceInvited;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Place", mappedBy="idUserPresent")
*/
protected $idPlacePresent;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Place", inversedBy="idUserPlace")
* #ORM\JoinTable(name="user_place",
* joinColumns={
* #ORM\JoinColumn(name="id_user_place", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="id_place_place", referencedColumnName="id")
* }
* )
*/
protected $idPlacePlace;
/**
* #var array
* #ORM\Column(type="simple_array", length=200)
* #Serializer\Exclude()
*/
protected $roles;
/**
* Constructor
*/
public function __construct()
{
$this->idUserTwo = new \Doctrine\Common\Collections\ArrayCollection();
$this->idPlaceInvited = new \Doctrine\Common\Collections\ArrayCollection();
$this->idPlacePresent = new \Doctrine\Common\Collections\ArrayCollection();
$this->idPlacePlace = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param int $id
*/
public function setId(int $id)
{
$this->id = $id;
}
/**
* #return string|null
*/
public function getUsername()
{
return $this->username;
}
/**
* #param string $username
*/
public function setUsername(string $username)
{
$this->username = $username;
}
/**
* #return string|null
*/
public function getPassword()
{
return $this->password;
}
/**
* #param string $password
*/
public function setPassword(string $password)
{
$this->password = $password;
}
/**
* #return bool
*/
public function isEnabled()
{
return $this->enabled;
}
/**
* #param bool $enabled
*/
public function setEnabled(bool $enabled)
{
$this->enabled = $enabled;
}
/**
* #return mixed
*/
public function getIdLocation()
{
return $this->idLocation;
}
/**
* #param mixed $idLocation
*/
public function setIdLocation($idLocation)
{
$this->idLocation = $idLocation;
}
/**
* #return mixed
*/
public function getIdProfile()
{
return $this->idProfile;
}
/**
* #param mixed $idProfile
*/
public function setIdProfile($idProfile)
{
$this->idProfile = $idProfile;
}
/**
* #return \Doctrine\Common\Collections\Collection
*/
public function getIdUserTwo()
{
return $this->idUserTwo;
}
/**
* #param \Doctrine\Common\Collections\Collection $idUserTwo
*/
public function setIdUserTwo(\Doctrine\Common\Collections\Collection $idUserTwo)
{
$this->idUserTwo = $idUserTwo;
}
/**
* #return \Doctrine\Common\Collections\Collection
*/
public function getIdPlaceInvited()
{
return $this->idPlaceInvited;
}
/**
* #param \Doctrine\Common\Collections\Collection $idPlaceInvited
*/
public function setIdPlaceInvited(\Doctrine\Common\Collections\Collection $idPlaceInvited)
{
$this->idPlaceInvited = $idPlaceInvited;
}
/**
* #return \Doctrine\Common\Collections\Collection
*/
public function getIdPlacePresent()
{
return $this->idPlacePresent;
}
/**
* #param \Doctrine\Common\Collections\Collection $idPlacePresent
*/
public function setIdPlacePresent(\Doctrine\Common\Collections\Collection $idPlacePresent)
{
$this->idPlacePresent = $idPlacePresent;
}
/**
* #return \Doctrine\Common\Collections\Collection
*/
public function getIdPlacePlace()
{
return $this->idPlacePlace;
}
/**
* #param \Doctrine\Common\Collections\Collection $idPlacePlace
*/
public function setIdPlacePlace(\Doctrine\Common\Collections\Collection $idPlacePlace)
{
$this->idPlacePlace = $idPlacePlace;
}
/**
* Returns the roles granted to the user.
*
* <code>
* public function getRoles()
* {
* return array('ROLE_USER');
* }
* </code>
*
* Alternatively, the roles might be stored on a ``roles`` property,
* and populated in any number of different ways when the user object
* is created.
*
* #return (Role|string)[] The user roles
*/
public function getRoles()
{
return $this->roles;
}
/**
* #param array $roles
*/
public function setRoles(array $roles)
{
$this->roles = $roles;
}
/**
* Returns the salt that was originally used to encode the password.
*
* This can return null if the password was not encoded using a salt.
*
* #return string|null The salt
*/
public function getSalt()
{
// TODO: Implement getSalt() method.
}
/**
* Removes sensitive data from the user.
*
* This is important if, at any given point, sensitive information like
* the plain-text password is stored on this object.
*/
public function eraseCredentials()
{
// TODO: Implement eraseCredentials() method.
}
}
some screen of data base : [https://ibb.co/iCSnWy
p
[https://ibb.co/cZZedd
p
In this case you'll have to do it this way:
$loggedAs = $this->getUser(); // get the user
$profile = new Profile();
// set up profile variables
// [...]
$profile->setUser($loggedAs); // case 1
// or, depending on your implementation
$loggedAs->addProfile($profile); // case 2
// persist, flush etc
With doctrine the foreign key handling is behind the scenes,
you don't have to worry about them if your mappings are correct
So instead of fkeys, you just attach entities.
Depending on your implementation (the relation can be uni- or bi-directional) you only have to chose one of the 2 cases.
I hope it helps, more here and here.

Symfony foreign keys (How can i edit them ?)

I have a little problem i don't know why i can't edit my foreign key ($idProfile) but i can edit an other value from the database :
I can change the value enable for exemple but not the idProfile when i try to change it i have this error : "An instance of Symfony\Bundle\FrameworkBundle\Templating\EngineInterface must be injected in FOS\RestBundle\View\ViewHandler to render templates." don't know if that can help thx for help guys :p
In general : I just want to know how can i edit my $id_profile to link it with my profile entity
my Profile controller :
/**
* Creates a new profile entity.
*
* #Route("/new/{id}", name="profile_new")
*/
public function newProfileAction(Request $request, User $user)
{
$loggedAs = $this->getUser();
$username = $loggedAs->getUsername();
$profile = new Profile();
$form = $this->createForm(ProfileType::class, $profile);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$profile->setLastConnexion(new \DateTime('now'));
$profile->setCreatedAccount(new \DateTime('now'));
$em = $this->getDoctrine()->getManager();
$em->persist($profile);
$em->flush();
$user->setEnabled('1');
$user->setIdLocation($profile->getId());
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
return $this->redirectToRoute('user_list');
}
return $this->render('admin/user/new_profile.html.twig', array(
'profile' => $profile,
'form' => $form->createView(),
'username' => $username,
));
}
My userEntity :
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
/**
* User
*
* #ORM\Table(name="user", uniqueConstraints=
{#ORM\UniqueConstraint(name="user_id_uindex", columns={"id"}),
#ORM\UniqueConstraint(name="user_username_uindex", columns=
{"username"})}, indexes={#ORM\Index(name="user_profile_id_fk",
columns={"id_profile"}), #ORM\Index(name="user_localisation_id_fk",
columns={"id_location"})})
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* #UniqueEntity("username", groups={"Default", "Patch"})
*/
class User implements UserInterface
{
const ROLE_USER = 'ROLE_USER';
const ROLE_ADMIN = 'ROLE_ADMIN';
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #Serializer\Groups({"Default", "Deserialize", "user_detail"})
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="username", type="string", length=32)
* #Serializer\Groups({"Default", "Deserialize", "user_detail"})
*/
protected $username;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255)
* #Serializer\Groups({"Deserialize", "user_detail"})
* #Assert\Regex(
* pattern="/(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).{7,}/",
* message="Password must be seven characters long and contain at least one digit code, upper case, and lower case letter!",
* groups={"Default", "Patch"}
* )
*/
protected $password;
/**
* #var boolean
*
* #ORM\Column(name="enabled", type="boolean", nullable=false)
*/
protected $enabled = '1';
/**
* #var \AppBundle\Entity\Localisation
*
* #ORM\ManyToOne(targetEntity="Localisation")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_location", referencedColumnName="id")
* })
*/
protected $idLocation;
/**
* #var \AppBundle\Entity\Profile
*
* #ORM\ManyToOne(targetEntity="Profile")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_profile", referencedColumnName="id")
* })
*/
protected $idProfile;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="User", inversedBy="idUserOne")
* #ORM\JoinTable(name="friend",
* joinColumns={
* #ORM\JoinColumn(name="id_user_one", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="id_user_two", referencedColumnName="id")
* }
* )
*/
protected $idUserTwo;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Place", inversedBy="idUserInvited")
* #ORM\JoinTable(name="list_invited",
* joinColumns={
* #ORM\JoinColumn(name="id_user_invited", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="id_place_invited", referencedColumnName="id")
* }
* )
*/
protected $idPlaceInvited;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Place", mappedBy="idUserPresent")
*/
protected $idPlacePresent;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Place", inversedBy="idUserPlace")
* #ORM\JoinTable(name="user_place",
* joinColumns={
* #ORM\JoinColumn(name="id_user_place", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="id_place_place", referencedColumnName="id")
* }
* )
*/
protected $idPlacePlace;
/**
* #var array
* #ORM\Column(type="simple_array", length=200)
* #Serializer\Exclude()
*/
protected $roles;
/**
* Constructor
*/
public function __construct()
{
$this->idUserTwo = new \Doctrine\Common\Collections\ArrayCollection();
$this->idPlaceInvited = new \Doctrine\Common\Collections\ArrayCollection();
$this->idPlacePresent = new \Doctrine\Common\Collections\ArrayCollection();
$this->idPlacePlace = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param int $id
*/
public function setId(int $id)
{
$this->id = $id;
}
/**
* #return string|null
*/
public function getUsername()
{
return $this->username;
}
/**
* #param string $username
*/
public function setUsername(string $username)
{
$this->username = $username;
}
/**
* #return string|null
*/
public function getPassword()
{
return $this->password;
}
/**
* #param string $password
*/
public function setPassword(string $password)
{
$this->password = $password;
}
/**
* #return bool
*/
public function isEnabled()
{
return $this->enabled;
}
/**
* #param bool $enabled
*/
public function setEnabled(bool $enabled)
{
$this->enabled = $enabled;
}
/**
* #return mixed
*/
public function getIdLocation()
{
return $this->idLocation;
}
/**
* #param mixed $idLocation
*/
public function setIdLocation($idLocation)
{
$this->idLocation = $idLocation;
}
/**
* #return mixed
*/
public function getIdProfile()
{
return $this->idProfile;
}
/**
* #param mixed $idProfile
*/
public function setIdProfile($idProfile)
{
$this->idProfile = $idProfile;
}
/**
* #return \Doctrine\Common\Collections\Collection
*/
public function getIdUserTwo()
{
return $this->idUserTwo;
}
/**
* #param \Doctrine\Common\Collections\Collection $idUserTwo
*/
public function setIdUserTwo(\Doctrine\Common\Collections\Collection $idUserTwo)
{
$this->idUserTwo = $idUserTwo;
}
/**
* #return \Doctrine\Common\Collections\Collection
*/
public function getIdPlaceInvited()
{
return $this->idPlaceInvited;
}
/**
* #param \Doctrine\Common\Collections\Collection $idPlaceInvited
*/
public function setIdPlaceInvited(\Doctrine\Common\Collections\Collection $idPlaceInvited)
{
$this->idPlaceInvited = $idPlaceInvited;
}
/**
* #return \Doctrine\Common\Collections\Collection
*/
public function getIdPlacePresent()
{
return $this->idPlacePresent;
}
/**
* #param \Doctrine\Common\Collections\Collection $idPlacePresent
*/
public function setIdPlacePresent(\Doctrine\Common\Collections\Collection $idPlacePresent)
{
$this->idPlacePresent = $idPlacePresent;
}
/**
* #return \Doctrine\Common\Collections\Collection
*/
public function getIdPlacePlace()
{
return $this->idPlacePlace;
}
/**
* #param \Doctrine\Common\Collections\Collection $idPlacePlace
*/
public function setIdPlacePlace(\Doctrine\Common\Collections\Collection $idPlacePlace)
{
$this->idPlacePlace = $idPlacePlace;
}
/**
* Returns the roles granted to the user.
*
* <code>
* public function getRoles()
* {
* return array('ROLE_USER');
* }
* </code>
*
* Alternatively, the roles might be stored on a ``roles`` property,
* and populated in any number of different ways when the user object
* is created.
*
* #return (Role|string)[] The user roles
*/
public function getRoles()
{
return $this->roles;
}
/**
* #param array $roles
*/
public function setRoles(array $roles)
{
$this->roles = $roles;
}
/**
* Returns the salt that was originally used to encode the password.
*
* This can return null if the password was not encoded using a salt.
*
* #return string|null The salt
*/
public function getSalt()
{
// TODO: Implement getSalt() method.
}
/**
* Removes sensitive data from the user.
*
* This is important if, at any given point, sensitive information like
* the plain-text password is stored on this object.
*/
public function eraseCredentials()
{
// TODO: Implement eraseCredentials() method.
}
}
some screen of data base : [https://ibb.co/iCSnWy
p
[https://ibb.co/cZZedd
p
you defined profile as type of \AppBundle\Entity\Profile this is the right way to work with doctrine. No to understand what is the difference in your entities and your database...
In the entities you need to set the entity not the id. Doctrine will then passt the id in the database, and when you get the entity from doctrine it will parse the id to an entity.
This means:
$user->setIdLocation($profile); //<-- set the entity
$profil = $user->getIdLocation(); // get the profile not the id

How to use Doctrine2 getScheduledEntityUpdates()

BudgetItem is related as ManyToOne to Budget and to Product. Here are the 3 entities:
BudgetItem
<?php
namespace CDGBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use CDGBundle\Entity\Product;
/**
* BudgetItem
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="CDGBundle\Entity\Repository\BudgetItemRepository")
* #ORM\HasLifecycleCallbacks
*/
class BudgetItem
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Product")
* #ORM\JoinColumn(nullable=false)
*/
private $product;
/**
* #var integer
*
* #ORM\Column(name="meters", type="integer")
*/
private $meters;
/**
* #var string
*
* #ORM\Column(name="price", type="decimal", scale=2)
*/
private $price;
/**
* #ORM\ManyToOne(targetEntity="Budget", inversedBy="items")
* #ORM\JoinColumn(nullable=false, onDelete="CASCADE")
*/
private $budget;
/**
* To String
*
* #return string
*/
public function __toString()
{
return $this->getProduct()->getName();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set budget
*
* #param integer $budget
*
* #return BudgetItem
*/
public function setBudget(Budget $budget)
{
$this->budget = $budget;
return $this;
}
/**
* Get budget
*
* #return integer
*/
public function getBudget()
{
return $this->budget;
}
/**
* Set product
*
* #param integer $product
*
* #return BudgetItem
*/
public function setProduct(Product $product = null)
{
$this->product = $product;
return $this;
}
/**
* Get product
*
* #return integer
*/
public function getProduct()
{
return $this->product;
}
/**
* Set meters
*
* #param integer $meters
*
* #return BudgetItem
*/
public function setMeters($meters)
{
$this->meters = $meters;
return $this;
}
/**
* Get meters
*
* #return integer
*/
public function getMeters()
{
return $this->meters;
}
/**
* Set price
*
* #param string $price
*
* #return BudgetItem
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* Get price
*
* #return string
*/
public function getPrice()
{
return $this->price;
}
/**
* #return integer;
*/
public function decreaseProductMeters()
{
return $this->getProduct()->getMeters() - $this->getMeters();
}
/**
* #ORM\PrePersist
*/
public function onPreEvents()
{
$this->getProduct()->setMeters($this->decreaseProductMeters());
}
public function onFlush(\Doctrine\ORM\Event\OnFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
foreach ($uow->getScheduledEntityUpdates() as $entity) {
$entity->getProduct();
$em->persist($entity);
$uow->recomputeSingleEntityChangeSet($em->getClassMetadata(get_class($entity)), $entity);
}
}
}
Budget
<?php
namespace CDGBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use CDGBundle\Entity\Customer;
use CDGBundle\Entity\BudgetItem;
/**
* Budget
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="CDGBundle\Entity\Repository\BudgetRepository")
* #ORM\HasLifecycleCallbacks
*/
class Budget
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\ManyToOne(targetEntity="Customer", inversedBy="budgets")
*/
private $customer;
/**
* #var integer
*
* #ORM\OneToMany(targetEntity="BudgetItem", mappedBy="budget", cascade={"persist"})
*/
private $items;
/**
* #var string
*
* #ORM\Column(name="address", type="string", length=255)
*/
private $address;
/**
* #var integer
*
* #ORM\Column(name="installment_rate", type="integer")
*/
private $installmentRate;
/**
* #var integer
*
* #ORM\Column(name="check_for", type="integer")
*/
private $checkFor;
/**
* #var \DateTime
*
* #ORM\Column(name="starts_at", type="datetime", nullable=true)
*/
private $startsAt;
/**
* #var \DateTime
*
* #ORM\Column(name="deadline", type="datetime", nullable=true)
*/
private $deadline;
/**
* #var string
*
* #ORM\Column(name="is_approved", type="string", length=1, nullable=true)
*/
private $isApproved;
/**
* #var string
*
* #ORM\Column(name="has_started", type="string", length=1, nullable=true)
*/
private $hasStarted;
/**
* #var decimal
*
* #ORM\Column(name="installment_rate_price", type="decimal", scale=2, nullable=true)
*/
private $installmentRatePrice;
/**
* #var decimal
*
* #ORM\Column(name="total_budget_price", type="decimal", scale=2, nullable=true)
*/
private $totalBudgetPrice;
/**
* #var \DateTime
*
* #ORM\Column(name="next_payment_date", type="datetime", nullable=true)
*/
private $nextPaymentDate;
/**
* #var string
*
* #ORM\Column(name="is_paid", type="string", length=1)
*/
private $isPaid;
/**
* #var string
*
* #ORM\Column(name="obs", type="text", nullable=true)
*/
private $obs;
/**
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime")
*/
private $createdAt;
/**
* Constructor
*/
public function __construct()
{
$this->items = new ArrayCollection();
$this->createdAt = new \DateTime();
$this->isPaid = 'n';
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set address
*
* #param string $address
*
* #return Budget
*/
public function setAddress($address)
{
$this->address = $address;
return $this;
}
/**
* Get address
*
* #return string
*/
public function getAddress()
{
return $this->address;
}
/**
* Set installmentRate
*
* #param integer $installmentRate
*
* #return Budget
*/
public function setInstallmentRate($installmentRate)
{
$this->installmentRate = $installmentRate;
return $this;
}
/**
* Get installmentRate
*
* #return integer
*/
public function getInstallmentRate()
{
return $this->installmentRate;
}
/**
* Set checkFor
*
* #param integer $checkFor
*
* #return Budget
*/
public function setCheckFor($checkFor)
{
$this->checkFor = $checkFor;
return $this;
}
/**
* Get checkFor
*
* #return integer
*/
public function getCheckFor()
{
return $this->checkFor;
}
/**
* Set startsAt
*
* #param \DateTime $startsAt
*
* #return Budget
*/
public function setStartsAt($startsAt)
{
$this->startsAt = $startsAt;
return $this;
}
/**
* Get startsAt
*
* #return \DateTime
*/
public function getStartsAt()
{
return $this->startsAt;
}
/**
* Set deadline
*
* #param \DateTime $deadline
*
* #return Budget
*/
public function setDeadline($deadline)
{
$this->deadline = $deadline;
return $this;
}
/**
* Get deadline
*
* #return \DateTime
*/
public function getDeadline()
{
return $this->deadline;
}
/**
* Set isApproved
*
* #param string $isApproved
*
* #return Budget
*/
public function setIsApproved($isApproved)
{
$this->isApproved = $isApproved;
return $this;
}
/**
* Get isApproved
*
* #return string
*/
public function getIsApproved()
{
return $this->isApproved;
}
/**
* Set hasStarted
*
* #param string $hasStarted
*
* #return Budget
*/
public function setHasStarted($hasStarted)
{
$this->hasStarted = $hasStarted;
return $this;
}
/**
* Get hasStarted
*
* #return string
*/
public function getHasStarted()
{
return $this->hasStarted;
}
/**
* Set installmentRatePrice
*
* #param string $installmentRatePrice
*
* #return Budget
*/
public function setInstallmentRatePrice($installmentRatePrice)
{
$this->installmentRatePrice = $installmentRatePrice;
return $this;
}
/**
* Get installmentRatePrice
*
* #return string
*/
public function getInstallmentRatePrice()
{
return $this->installmentRatePrice;
}
/**
* Set totalBudgetPrice
*
* #param string $totalBudgetPrice
*
* #return Budget
*/
public function setTotalBudgetPrice($totalBudgetPrice)
{
$this->totalBudgetPrice = $totalBudgetPrice;
return $this;
}
/**
* Get totalBudgetPrice
*
* #return string
*/
public function getTotalBudgetPrice()
{
return $this->totalBudgetPrice;
}
/**
* Set nextPaymentDate
*
* #param \DateTime $nextPaymentDate
*
* #return Budget
*/
public function setNextPaymentDate($nextPaymentDate)
{
$this->nextPaymentDate = $nextPaymentDate;
return $this;
}
/**
* Get nextPaymentDate
*
* #return \DateTime
*/
public function getNextPaymentDate()
{
return $this->nextPaymentDate;
}
/**
* Set isPaid
*
* #param string $isPaid
*
* #return Budget
*/
public function setIsPaid($isPaid)
{
$this->isPaid = $isPaid;
return $this;
}
/**
* Get isPaid
*
* #return string
*/
public function getIsPaid()
{
return $this->isPaid;
}
/**
* Set obs
*
* #param string $obs
*
* #return Budget
*/
public function setObs($obs)
{
$this->obs = $obs;
return $this;
}
/**
* Get obs
*
* #return string
*/
public function getObs()
{
return $this->obs;
}
/**
* Set createdAt
*
* #param \DateTime $createdAt
*
* #return Budget
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Get createdAt
*
* #return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Set customer
*
* #param Customer $customer
*
* #return Budget
*/
public function setCustomer(Customer $customer = null)
{
$this->customer = $customer;
return $this;
}
/**
* Get customer
*
* #return Customer
*/
public function getCustomer()
{
return $this->customer;
}
/**
* Add item
*
* #param BudgetItem $item
*
* #return Budget
*/
public function addItem(BudgetItem $item)
{
$item->setBudget($this);
$this->items->add($item);
return $this;
}
/**
* Remove item
*
* #param BudgetItem $item
*/
public function removeItem(BudgetItem $item)
{
$this->items->removeElement($item);
}
/**
* Get items
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getItems()
{
return $this->items;
}
/**
* #return \DateTime
*/
public function generateNextPaymentDate()
{
if ($this->getStartsAt() !== null) {
$date = new \DateTime($this->getStartsAt()->format('Y-m-d'));
return $date->add(new \DateInterval('P' . $this->getCheckFor() . 'D'));
}
}
/**
* #return decimal
*/
public function calculateTotalBudgetPrice()
{
$totalBudgetPrice = 0;
foreach ($this->getItems() as $item) {
$totalBudgetPrice += $item->getPrice();
}
return $totalBudgetPrice;
}
/**
* #return decimal
*/
public function calculateInstallmentRatePrice()
{
return $this->calculateTotalBudgetPrice() / $this->getInstallmentRate();
}
/**
* #ORM\PrePersist
* #ORM\PreUpdate
*/
public function onPreEvents()
{
$this->setNextPaymentDate($this->generateNextPaymentDate());
$this->setInstallmentRatePrice($this->calculateInstallmentRatePrice());
$this->setTotalBudgetPrice($this->calculateTotalBudgetPrice());
}
}
Product
<?php
namespace CDGBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use CDGBundle\Entity\ProductType;
/**
* Product
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="CDGBundle\Entity\Repository\ProductRepository")
* #ORM\HasLifecycleCallbacks
*/
class Product
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #var string
*
* #ORM\ManyToOne(targetEntity="ProductType")
* #ORM\JoinColumn(nullable=false, onDelete="CASCADE")
*/
private $type;
/**
* #var string
*
* #ORM\Column(name="price", type="decimal", scale=2)
*/
private $price;
/**
* #var integer
*
* #ORM\Column(name="meters", type="integer", nullable=true)
*/
private $meters;
/**
* #var string
*
* #ORM\Column(name="description", type="text", nullable=true)
*/
private $description;
/**
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime")
*/
private $createdAt;
/**
* Constructor
*/
public function __construct()
{
$this->createdAt = new \DateTime();
}
/**
* To String
*
* #return string
*/
public function __toString()
{
return $this->name;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Product
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set type
*
* #param \CDGBundle\Entity\ProductType $type
*
* #return Product
*/
public function setType(ProductType $type)
{
$this->type = $type;
return $this;
}
/**
* Get type
*
* #return \CDGBundle\Entity\ProductType
*/
public function getType()
{
return $this->type;
}
/**
* Set price
*
* #param string $price
*
* #return Product
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* Get price
*
* #return string
*/
public function getPrice()
{
return $this->price;
}
/**
* Set meters
*
* #param integer $meters
*
* #return Product
*/
public function setMeters($meters)
{
$this->meters = $meters;
return $this;
}
/**
* Get meters
*
* #return integer
*/
public function getMeters()
{
return $this->meters;
}
/**
* Set description
*
* #param string $description
*
* #return Product
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set createdAt
*
* #param \DateTime $createdAt
*
* #return Product
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Get createdAt
*
* #return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
}
Product is a collection form inside of Budget. It lists all the registered products to choose when registering a new budget. I have all the necessary JavaScript and a macro to show the form.
I need to update the total amount of meters from Product entity when EDITING an existing Budget. I have an onFlush method inside of BudgetItem for this:
public function onFlush(\Doctrine\ORM\Event\OnFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
foreach ($uow->getScheduledEntityUpdates() as $entity) {
$entity->getItems();
$em->persist($entity);
$uow->recomputeSingleEntityChangeSet($em->getClassMetadata(get_class($entity)), $entity);
}
}
Now here is my problem. I do not know what to do inside of the foreach method. I need to do the same as I do in the PrePersist method, but I get different errors.
Inside of the loop, if I do $entity->getItems(), I get the error:
Attempted to call an undefined method named "getItems" of class "CDGBundle\Entity\BudgetItem".
If I do $entity->getProduct(), the error:
Attempted to call an undefined method named "getProduct" of class "CDGBundle\Entity\Budget".
Why does it magically change the entity? For God sake someone help me with this. Doctrine2 has a too complicated updating event.
In a Doctrine listener, you always need to check the class of the entity, since every single updated items are stored in your getScheduledEntityUpdates() method.
The solution is to test if updated entity is an instance of Budget:
foreach ($uow->getScheduledEntityUpdates() as $entity) {
if ($entity instanceof Budget) {
// $entity is a Budget entity
// ... your code here
}
}

Form nulling a value when user doesn't supply it

Reading this page I've setup a form to handle PATCH requests.
I've a Player entity:
<?php
namespace Acme\PlayerBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
/**
* Acme\PlayerBundle\Entity\Player
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Acme\PlayerBundle\Entity\PlayerRepository")
*/
class Player
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=255)
* #Assert\NotBlank()
*/
private $name;
/**
* #ORM\ManyToOne(targetEntity="Acme\UserBundle\Entity\User", inversedBy="players")
* #ORM\JoinColumn(nullable=false)
*/
private $owner;
/**
* #ORM\ManyToOne(targetEntity="Acme\TeamBundle\Entity\Team", inversedBy="players")
* #ORM\JoinColumn(nullable=false)
* #Assert\NotBlank()
*/
private $team;
/**
* #var integer $shirtNumber
*
* #ORM\Column(name="shirtNumber", type="smallint")
* #Assert\NotBlank()
*/
private $shirtNumber;
/**
* #var integer $vsid
*
* #ORM\Column(name="vsid", type="integer", nullable=true)
*/
private $vsid;
/**
* #var string $firstname
*
* #ORM\Column(name="firstname", type="string", length=255, nullable=true)
*/
private $firstname;
/**
* #var string $lastname
*
* #ORM\Column(name="lastname", type="string", length=255, nullable=true)
*/
private $lastname;
/**
* #var boolean $deleted
*
* #ORM\Column(name="deleted", type="boolean")
*/
private $deleted = false;
/**
* #var integer $role
*
* #ORM\Column(type="integer", nullable=true)
*/
private $role;
/**
* Create the user salt
*/
public function __construct()
{
//TODO: just for test
$this->uniqueId = substr(uniqid(), 0, 14);
}
/* MANAGED BY DOCTRINE, DON'T EDIT */
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Player
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set shirtNumber
*
* #param integer $shirtNumber
* #return Player
*/
public function setShirtNumber($shirtNumber)
{
$this->shirtNumber = $shirtNumber;
return $this;
}
/**
* Get shirtNumber
*
* #return integer
*/
public function getShirtNumber()
{
return $this->shirtNumber;
}
/**
* Set vsid
*
* #param integer $vsid
* #return Player
*/
public function setVsid($vsid)
{
$this->vsid = $vsid;
return $this;
}
/**
* Get vsid
*
* #return integer
*/
public function getVsid()
{
return $this->vsid;
}
/**
* Set firstname
*
* #param string $firstname
* #return Player
*/
public function setFirstname($firstname)
{
$this->firstname = $firstname;
return $this;
}
/**
* Get firstname
*
* #return string
*/
public function getFirstname()
{
return $this->firstname;
}
/**
* Set lastname
*
* #param string $lastname
* #return Player
*/
public function setLastname($lastname)
{
$this->lastname = $lastname;
return $this;
}
/**
* Get lastname
*
* #return string
*/
public function getLastname()
{
return $this->lastname;
}
/**
* Set deleted
*
* #param boolean $deleted
* #return Player
*/
public function setDeleted($deleted)
{
$this->deleted = $deleted;
return $this;
}
/**
* Get deleted
*
* #return boolean
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Set role
*
* #param integer $role
* #return Player
*/
public function setRole($role)
{
$this->role = $role;
return $this;
}
/**
* Get role
*
* #return integer
*/
public function getRole()
{
return $this->role;
}
/**
* Set owner
*
* #param Acme\UserBundle\Entity\User $owner
* #return Player
*/
public function setOwner(\Acme\UserBundle\Entity\User $owner)
{
$this->owner = $owner;
return $this;
}
/**
* Get owner
*
* #return Acme\UserBundle\Entity\User
*/
public function getOwner()
{
return $this->owner;
}
/**
* Set team
*
* #param Acme\TeamBundle\Entity\Team $team
* #return Player
*/
public function setTeam(\Acme\TeamBundle\Entity\Team $team)
{
$this->team = $team;
return $this;
}
/**
* Get team
*
* #return Acme\TeamBundle\Entity\Team
*/
public function getTeam()
{
return $this->team;
}
}
and a Team entity:
<?php
namespace Acme\TeamBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Acme\TeamBundle\Entity\Team
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Acme\TeamBundle\Entity\TeamRepository")
*/
class Team
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $uniqueId
*
* #ORM\Column(name="uniqueId", type="string", length=15)
*/
private $uniqueId;
/**
* #ORM\ManyToOne(targetEntity="Acme\UserBundle\Entity\User", inversedBy="teams")
* #ORM\JoinColumn(nullable=false)
*/
private $owner;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=50)
* #Assert\NotBlank()
*/
private $name;
/**
* #var string $homeColor
*
* #ORM\Column(name="homeColor", type="string", length=7, nullable=true)
*/
private $homeColor;
/**
* #var string $awayColor
*
* #ORM\Column(name="awayColor", type="string", length=7, nullable=true)
*/
private $awayColor;
/**
* #var string $homeShirt
*
* #ORM\Column(name="homeShirt", type="string", length=50, nullable=true)
*/
private $homeShirt;
/**
* #var string $awayShirt
*
* #ORM\Column(name="awayShirt", type="string", length=50, nullable=true)
*/
private $awayShirt;
/**
* #var string $teamLogo
*
* #ORM\Column(name="teamLogo", type="string", length=50, nullable=true)
*/
private $teamLogo;
/**
* #var boolean $deleted
*
* #ORM\Column(name="deleted", type="boolean")
*/
private $deleted = false;
/**
* #ORM\OneToMany(targetEntity="Acme\PlayerBundle\Entity\Player", mappedBy="team", cascade={"persist", "remove"})
*/
private $players;
/**
* #ORM\OneToMany(targetEntity="Acme\MatchBundle\Entity\Match", mappedBy="homeTeam")
*/
private $homeMatches;
/**
* #ORM\OneToMany(targetEntity="Acme\MatchBundle\Entity\Match", mappedBy="awayTeam")
*/
private $awayMatches;
/**
* Create the user salt
*/
public function __construct()
{
$this->players = new ArrayCollection();
$this->homeMatches = new ArrayCollection();
$this->awayMatches = new ArrayCollection();
//TODO: just for test
$this->uniqueId = substr(uniqid(), 0, 14);
}
public function getMatches()
{
return array_merge($this->awayMatches->toArray(), $this->homeMatches->toArray());
}
/* MANAGED BY DOCTRINE, DON'T EDIT */
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set uniqueId
*
* #param string $uniqueId
* #return Team
*/
public function setUniqueId($uniqueId)
{
$this->uniqueId = $uniqueId;
return $this;
}
/**
* Get uniqueId
*
* #return string
*/
public function getUniqueId()
{
return $this->uniqueId;
}
/**
* Set name
*
* #param string $name
* #return Team
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set homeColor
*
* #param string $homeColor
* #return Team
*/
public function setHomeColor($homeColor)
{
$this->homeColor = $homeColor;
return $this;
}
/**
* Get homeColor
*
* #return string
*/
public function getHomeColor()
{
return $this->homeColor;
}
/**
* Set awayColor
*
* #param string $awayColor
* #return Team
*/
public function setAwayColor($awayColor)
{
$this->awayColor = $awayColor;
return $this;
}
/**
* Get awayColor
*
* #return string
*/
public function getAwayColor()
{
return $this->awayColor;
}
/**
* Set homeShirt
*
* #param string $homeShirt
* #return Team
*/
public function setHomeShirt($homeShirt)
{
$this->homeShirt = $homeShirt;
return $this;
}
/**
* Get homeShirt
*
* #return string
*/
public function getHomeShirt()
{
return $this->homeShirt;
}
/**
* Set awayShirt
*
* #param string $awayShirt
* #return Team
*/
public function setAwayShirt($awayShirt)
{
$this->awayShirt = $awayShirt;
return $this;
}
/**
* Get awayShirt
*
* #return string
*/
public function getAwayShirt()
{
return $this->awayShirt;
}
/**
* Set teamLogo
*
* #param string $teamLogo
* #return Team
*/
public function setTeamLogo($teamLogo)
{
$this->teamLogo = $teamLogo;
return $this;
}
/**
* Get teamLogo
*
* #return string
*/
public function getTeamLogo()
{
return $this->teamLogo;
}
/**
* Set deleted
*
* #param boolean $deleted
* #return Team
*/
public function setDeleted($deleted)
{
$this->deleted = $deleted;
return $this;
}
/**
* Get deleted
*
* #return boolean
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Add players
*
* #param Acme\PlayerBundle\Entity\Player $players
* #return Team
*/
public function addPlayer(\Acme\PlayerBundle\Entity\Player $players)
{
$this->players[] = $players;
return $this;
}
/**
* Remove players
*
* #param Acme\PlayerBundle\Entity\Player $players
*/
public function removePlayer(\Acme\PlayerBundle\Entity\Player $players)
{
$this->players->removeElement($players);
}
/**
* Get players
*
* #return Doctrine\Common\Collections\Collection
*/
public function getPlayers()
{
return $this->players;
}
/**
* Add homeMatches
*
* #param Acme\MatchBundle\Entity\Match $homeMatches
* #return Team
*/
public function addHomeMatche(\Acme\MatchBundle\Entity\Match $homeMatches)
{
$this->homeMatches[] = $homeMatches;
return $this;
}
/**
* Remove homeMatches
*
* #param Acme\MatchBundle\Entity\Match $homeMatches
*/
public function removeHomeMatche(\Acme\MatchBundle\Entity\Match $homeMatches)
{
$this->homeMatches->removeElement($homeMatches);
}
/**
* Get homeMatches
*
* #return Doctrine\Common\Collections\Collection
*/
public function getHomeMatches()
{
return $this->homeMatches;
}
/**
* Add awayMatches
*
* #param Acme\MatchBundle\Entity\Match $awayMatches
* #return Team
*/
public function addAwayMatche(\Acme\MatchBundle\Entity\Match $awayMatches)
{
$this->awayMatches[] = $awayMatches;
return $this;
}
/**
* Remove awayMatches
*
* #param Acme\MatchBundle\Entity\Match $awayMatches
*/
public function removeAwayMatche(\Acme\MatchBundle\Entity\Match $awayMatches)
{
$this->awayMatches->removeElement($awayMatches);
}
/**
* Get awayMatches
*
* #return Doctrine\Common\Collections\Collection
*/
public function getAwayMatches()
{
return $this->awayMatches;
}
/**
* Set owner
*
* #param Acme\UserBundle\Entity\User $owner
* #return Team
*/
public function setOwner(\Acme\UserBundle\Entity\User $owner)
{
$this->owner = $owner;
return $this;
}
/**
* Get owner
*
* #return Acme\UserBundle\Entity\User
*/
public function getOwner()
{
return $this->owner;
}
}
Now I've created a player form class with the app/console and I've edited the team field to be an instance of the Team entity, this way:
<?php
namespace Acme\PlayerBundle\Form;
use Acme\TeamBundle\Entity\TeamRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class PlayerType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('shirtNumber')
->add('firstname')
->add('lastname')
->add('role')
->add('team', 'entity', array(
'class' => 'AcmeTeamBundle:Team',
'query_builder' => function(TeamRepository $er) {
$query = $er->createQueryBuilder('t');
return $query;
}
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\PlayerBundle\Entity\Player',
'csrf_protection' => false
));
}
public function getName()
{
return 'player';
}
}
And this is the relevant part of my controller:
/**
* Create a new player
*
* #Route(".{_format}", name="api_player_create")
* #Method("POST")
* #ApiDoc(
* description="Create a new player",
* statusCodes={
* 201="Player created and informations are returned",
* 400="Missing informations",
* 403="The user isn't authorized"
* },
* input="Acme\PlayerBundle\Form\PlayerType",
* return="Acme\PlayerBundle\Entity\Player"
* )
*
* #return Renders the player just created
*/
public function createPlayerAction()
{
return $this->processForm(new Player());
}
/**
* Edit a player
*
* #param integer $id The id of the player to be created
*
* #Route("/{id}.{_format}", name="api_player_patch", requirements={ "id": "\d+" })
* #Method("PATCH")
* #ApiDoc(
* description="Edit a player",
* statusCodes={
* 200="Player is updated",
* 400="Missing informations",
* 403="The user isn't authorized"
* },
* input="Acme\PlayerBundle\Form\PlayerType",
* return="Acme\PlayerBundle\Entity\Player"
* )
*
* #return Renders the player just edited
*/
public function editPlayerAction(Player $player)
{
if ($player->getOwner() != $this->getUser()) {
throw new ApiException\PermissionDeniedException;
}
return $this->processForm($player);
}
/**
* Function to handle a form to create/edit a player
*
* #param Player $player The player to be created or edited
*
* #return Api Response
*/
private function processForm(Player $player)
{
/**
* Check if the player is new (to be created) or we're editing a player
*/
$statusCode = is_null($player->getId()) ? 201 : 200;
$form = $this->createForm(new PlayerType(), $player);
$form->bind($this->getRequest());
if ($form->isValid()) {
if($player->getTeam()->getOwner() != $this->getUser()) {
throw new ApiException\PermissionDeniedException;
}
$player->setOwner($this->getUser());
$this->entityManager->persist($player);
$this->entityManager->flush();
return $this->apiResponse->getResponse($player, $statusCode);
}
return $this->apiResponse->getResponse($form, 400, 'Missing arguments');
}
The player creation works fine, the player edit doesn't, when the user makes the api request, passing the ID in the url and the name of the player I get:
Catchable Fatal Error: Argument 1 passed to Acme\PlayerBundle\Entity\Player::setTeam() must be an instance of Acme\TeamBundle\Entity\Team, null given, called in /Volumes/Dati/Users/alessandro/Sites/acme-api/vendor/symfony/symfony/src/Symfony/Component/Form/Util/PropertyPath.php on line 538 and defined in /Volumes/Dati/Users/alessandro/Sites/acme-api/src/Acme/PlayerBundle/Entity/Player.php line 278
Seems that form is trying to set the Team to null, why?
I've tried both sending and not the team as the form parameters but it doesn't work.
Any clue?
Figured it out that null unsent fields in the form is the default behaviour in symfony.
There is an open request for partial form binding in symfony. For now a guy created a form event subscriber that adds the missing fields with the actual values:
https://gist.github.com/3720535
This is his code:
<?php
namespace Foo;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
/**
* Changes Form->bind() behavior so that it treats not set values as if they
* were sent unchanged.
*
* Use when you don't want fields to be set to NULL when they are not displayed
* on the page (or to implement PUT/PATCH requests).
*/
class PatchSubscriber implements EventSubscriberInterface
{
public function onPreBind(FormEvent $event)
{
$form = $event->getForm();
$clientData = $event->getData();
$clientData = array_replace($this->unbind($form), $clientData ?: array());
$event->setData($clientData);
}
/**
* Returns the form's data like $form->bind() expects it
*/
protected function unbind($form)
{
if ($form->hasChildren()) {
$ary = array();
foreach ($form->getChildren() as $name => $child) {
$ary[$name] = $this->unbind($child);
}
return $ary;
} else {
return $form->getClientData();
}
}
static public function getSubscribedEvents()
{
return array(
FormEvents::PRE_BIND => 'onPreBind',
);
}
}
to add to the form you have to edit the buildForm method in the form class:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$subscriber = new PatchSubscriber();
$builder->addEventSubscriber($subscriber);
$builder->add('name');
....
}
In this case you're ok to use the PATCH REST requests to edit an entity just by the sent fields

Resources