Symfony4 - Undefined index: on entity join - symfony

I'm getting an
undefined index: order
error even though from what I can tell using this documentation I'm doing everything right. Any ideas?
OrdersRepository
public function findByDateAndEmployee(\DateTime $date, int $employeeId)
{
return $this->createQueryBuilder('o')
->select('o')
->join('o.employees' ,'e')
->where('e.id = :id')
->setParameter('id',$employeeId)
->getQuery()->getSql();
}
Orders Entity
class Orders
{
...
/**
* One Order has Many Employees.
* #ORM\OneToMany(targetEntity="Employee", mappedBy="order", cascade={"persist", "remove"}, orphanRemoval=TRUE)
*/
private $employees;
I know if I change the variable in "mappedBy" it will change the error message to whatever the variable name is, however when you see below "order" should be the mappedBy variable (at least, I think).
OrderEmployees Entity
class OrderEmployees
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="integer")
*/
private $orderId;
/**
* #ORM\Column(type="smallint")
*/
private $employeeId;
/**
* #ORM\ManyToOne(targetEntity="Orders", inversedBy="employees")
* #ORM\JoinColumn(name="order_id", referencedColumnName="id")
*/
private $order;
public function getId(): ?int
{
return $this->id;
}
public function getOrderId(): ?int
{
return $this->orderId;
}
public function setOrderId(int $orderId): self
{
$this->orderId = $orderId;
return $this;
}
public function getEmployeeId(): ?int
{
return $this->employeeId;
}
public function setEmployeeId(int $employeeId): self
{
$this->employeeId = $employeeId;
return $this;
}
public function getOrder(): Orders
{
return $this->order;
}
public function setOrder(Orders $order): self
{
$this->order = $order;
return $this;
}
}

Changing targetEntity="Employee" to targetEntity="OrderEmployees" in your Orders entity should help.
From the docs:
targetEntity: FQCN of the referenced target entity. Can be the
unqualified class name if both classes are in the same namespace.

Related

How to fetch data from many to many relation ship third table in symfony doctrine

I have an intermediate table that acts as a pivot between two others: user, punto_suministro and table pivot user_punto_suministro:
How to fetch data from table user to table punto_suministro?
Entity User:
/**
* #ORM\Entity(repositoryClass=UserRepository::class)
*/
class User implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
.....
/**
* #ORM\OneToMany(targetEntity=UserPuntoSuministro::class, mappedBy="user")
*/
private $userPuntoSuministros;
/**
* #throws \Exception
*/
public function __construct()
{
$this->puntoSuministros = new ArrayCollection();
$this->userPuntoSuministros = new ArrayCollection();
}
/**
* #return Collection|UserPuntoSuministro[]
*/
public function getUserPuntoSuministros(): Collection
{
return $this->userPuntoSuministros;
}
public function addUserPuntoSuministro(UserPuntoSuministro $userPuntoSuministro): self
{
if (!$this->userPuntoSuministros->contains($userPuntoSuministro)) {
$this->userPuntoSuministros[] = $userPuntoSuministro;
$userPuntoSuministro->setUser($this);
}
return $this;
}
public function removeUserPuntoSuministro(UserPuntoSuministro $userPuntoSuministro): self
{
if ($this->userPuntoSuministros->contains($userPuntoSuministro)) {
$this->userPuntoSuministros->removeElement($userPuntoSuministro);
// set the owning side to null (unless already changed)
if ($userPuntoSuministro->getUser() === $this) {
$userPuntoSuministro->setUser(null);
}
}
return $this;
}
Entity PuntoSuministro:
/**
* #ORM\Entity(repositoryClass=PuntoSuministroRepository::class)
*/
class PuntoSuministro
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
...
/**
* #ORM\OneToMany(targetEntity=UserPuntoSuministro::class, mappedBy="punto_suministro")
*/
private $userPuntoSuministros;
public function __construct()
{
$this->userPuntoSuministros = new ArrayCollection();
}
/**
* #return Collection|UserPuntoSuministro[]
*/
public function getUserPuntoSuministros(): Collection
{
return $this->userPuntoSuministros;
}
public function addUserPuntoSuministro(UserPuntoSuministro $userPuntoSuministro): self
{
if (!$this->userPuntoSuministros->contains($userPuntoSuministro)) {
$this->userPuntoSuministros[] = $userPuntoSuministro;
$userPuntoSuministro->setPuntoSuministro($this);
}
return $this;
}
public function removeUserPuntoSuministro(UserPuntoSuministro $userPuntoSuministro): self
{
if ($this->userPuntoSuministros->contains($userPuntoSuministro)) {
$this->userPuntoSuministros->removeElement($userPuntoSuministro);
// set the owning side to null (unless already changed)
if ($userPuntoSuministro->getPuntoSuministro() === $this) {
$userPuntoSuministro->setPuntoSuministro(null);
}
}
return $this;
}
Entity UserPuntoSuministro (table pivot):
/**
* #ORM\Entity(repositoryClass=UserPuntoSuministroRepository::class)
*/
class UserPuntoSuministro
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity=User::class, inversedBy="userPuntoSuministros")
*/
private $user;
/**
* #ORM\ManyToOne(targetEntity=PuntoSuministro::class, inversedBy="userPuntoSuministros")
*/
private $punto_suministro;
public function getId(): ?int
{
return $this->id;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
public function getPuntoSuministro(): ?PuntoSuministro
{
return $this->punto_suministro;
}
public function setPuntoSuministro(?PuntoSuministro $punto_suministro): self
{
$this->punto_suministro = $punto_suministro;
return $this;
}
I try and access as follows:
$user = $userRepository->find($this->security->getUser());
$pivote = $user->getUserPuntoSuministros();
but from here I don't know how to recover the punto_suministro of a user to show it on twig.
Thanks in advance.
In simple case you could iterate over $user->getUserPuntoSuministros() and fetch concrete punto_suministro's
$user = $userRepository->find($this->security->getUser());
$puntoSuministros = []; // contains PuntoSuministro's of User
foreach ($user->getUserPuntoSuministros() as $userPuntoSuministro) {
$puntoSuministros[] = $userPuntoSuministro->getPuntoSuministro();
}

ManyToMany error : Argument 1 passed to Doctrine\Common\Collections\ArrayCollection::__construct() must be of the type array, object given

I have a problem with type ManyToMany relations entities.
I learn symfony i make maybe something wrong.
I tried many ways (Without foreach ...) but i fall always on errors.
These entities were created whit the CLI.
Thanks for your replys and sorry for my bad english
My entities :
Clients
<?php
namespace App\Entity;
use App\Repository\ClientsRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass=ClientsRepository::class)
*/
class Clients
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $nom;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $prenom;
/**
* #ORM\Column(type="string", length=255)
*/
private $mail;
/**
* #ORM\Column(type="datetime")
*/
private $created_at;
/**
* #ORM\Column(type="boolean")
*/
private $actif;
/**
* #ORM\ManyToMany(targetEntity=Services::class, mappedBy="clients")
*/
private $services;
public function __construct()
{
$this->services = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getNom(): ?string
{
return $this->nom;
}
public function setNom(string $nom): self
{
$this->nom = $nom;
return $this;
}
public function getPrenom(): ?string
{
return $this->prenom;
}
public function setPrenom(?string $prenom): self
{
$this->prenom = $prenom;
return $this;
}
public function getMail(): ?string
{
return $this->mail;
}
public function setMail(string $mail): self
{
$this->mail = $mail;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->created_at;
}
public function setCreatedAt(\DateTimeInterface $created_at): self
{
$this->created_at = $created_at;
return $this;
}
public function getActif(): ?bool
{
return $this->actif;
}
public function setActif(bool $actif): self
{
$this->actif = $actif;
return $this;
}
/**
* #return Collection|Services[]
*/
public function getServices(): Collection
{
return $this->services;
}
public function addService(Services $service): self
{
if (!$this->services->contains($service)) {
$this->services[] = $service;
$service->setClients($this);
}
return $this;
}
public function removeService(Services $service): self
{
if ($this->services->contains($service)) {
$this->services->removeElement($service);
// set the owning side to null (unless already changed)
if ($service->getClients() === $this) {
$service->setClients(null);
}
}
return $this;
}
}
Services
<?php
namespace App\Entity;
use App\Repository\ServicesRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass=ServicesRepository::class)
*/
class Services
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $nom;
/**
* #ORM\Column(type="float")
*/
private $prix;
/**
* #ORM\ManyToMany(targetEntity=Clients::class, inversedBy="services")
*/
private $clients;
public function getId(): ?int
{
return $this->id;
}
public function getNom(): ?string
{
return $this->nom;
}
public function setNom(string $nom): self
{
$this->nom = $nom;
return $this;
}
public function getPrix(): ?float
{
return $this->prix;
}
public function setPrix(float $prix): self
{
$this->prix = $prix;
return $this;
}
public function getClients(): ?Clients
{
return $this->clients;
}
public function setClients(?Clients $clients): self
{
$this->clients = $clients;
return $this;
}
}
Controller
[...]
$entityManager = $this->getDoctrine()->getManager();
foreach($servicesClient as $srv){
$service = $this->getDoctrine()->getRepository(Services::class)->find($srv);
$service->setClients($client);
$client->addService($service);
$entityManager->persist($client);
$entityManager->persist($service);
$entityManager->flush();
}
[...]
Your Service::clients property is marked with #ManyToMany annotation, which means it should be typed #var Collection|Clients[] but both getter and setter returns/set a nullable object ?Clients $clients.
No way the bin/console make:entity did that.
You should use the same system as your Clients::services property, i.e using three methods getClients(), addClients() and removeClients() without setClients(). Besides, you need a constructor starting the $clients property: $this->clients = new ArrayCollection();.
Or maybe you want to use #OneToMany and #ManyToOne annotations.
Note that an entity classname should be singular.

showing only current user's relations

I have 2 entities, User and courses, each student can have many courses and each course can have many students. Anyway, I'm trying to make it so that when a user connects to his account, it shows him all the courses he's related to. I know I have to do it from my controller but how do I get only the ones he's related to.
my entities
<?php
/**
* #ORM\Entity
*/
class User implements UserInterface
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
public function getId()
{
return $this->id;
}
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Courses", mappedBy="Users")
*/
private $courses;
public function __construct()
{
$this->courses = new ArrayCollection();
}
/**
* #return Collection|course[]
*/
public function getCourses(): Collection
{
return $this->courses;
}
public function addCourse(Course $course): self
{
if (!$this->courses->contains($course)) {
$this->courses[] = $course;
$course->addUser($this);
return $this;
}
return $this;
}
public function removeCourse(Course $course): self
{
if ($this->courses->contains($course)) {
$this->courses->removeElement($course);
$course->removeUser($this);
}
return $this;
}
}
<?php
/**
* #ORM\Entity(repositoryClass="App\Repository\CourseRepository")
*/
class Course
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=55)
*/
private $name;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\user", inversedBy="courses")
*/
private $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getname(): ?string
{
return $this->name;
}
public function setname(string $name): self
{
$this->name = $name;
return $this;
}
/**
* #return Collection|user[]
*/
public function getUser(): Collection
{
return $this->user;
}
public function addUser(user $user): self
{
if (!$this->users->contains($user)) {
$this->users[] = $user;
}
return $this;
}
public function removeUser(user $user): self
{
if ($this->users->contains($user)) {
$this->users->removeElement($user);
}
return $this;
}
}
Well, because you apparently have a bi-directional relationship (inversedBy and mappedBy) you dont need to do anything special. Doctrine has already done this. Just grab the user in the controller:
// Once you have a protected controller route,
// you can use $this->getUser() from inside the
// controller action to access the current authenticated user.
$user = $this->getUser();
And iterate as you'd like through their related courses:
foreach ($user->getCourses() as $course) {
}
Because getCourses also returns a Collection instance, you can also use the ->map and ->filter functions that ship with the Collection class...

how to insert into junction table when many to many with doctrine?

I am trying to insert into a junction table called post_post_category which is based on Post and PostCategory tables [many to many], i manage to execute the insert but the problem is that when i add a new post it creates a new category.
Post Entity:
class Post
{
...
/**
* #ORM\ManyToMany(targetEntity="PostCategory", cascade={"persist"})
* #ORM\JoinTable(name="post_post_category",
* joinColumns={#ORM\JoinColumn(name="post_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="post_category_id", referencedColumnName="id")}
* )
*/
private $categories;
public function __construct() {
$this->categories = new ArrayCollection();
}
...
public function getCategories(): ?PostCategory
{
return $this->categories;
}
public function addCategory(PostCategory $category): self
{
$this->categories->add($category);
return $this;
}
}
Category Entity:
class PostCategory
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=60)
*/
private $category_description;
public function getId()
{
return $this->id;
}
public function getCategoryDescription(): ?string
{
return $this->category_description;
}
public function setCategoryDescription(string $category_description): self
{
$this->category_description = $category_description;
return $this;
}
}
Controller:
...
$category->setCategoryDescription('New category');
$post->addCategory($category);
$database_manager->persist($post);
$database_manager->flush();
How do i insert an existing category in junction table?
to add an existing category to a Post you will have to retrieve the category from the database
$category = $em->getRepository('AppBundle:PostCategory')->find($categoryId);
$post->addCategory($category);

Symfony, oneToMany relationship Invalid argument supplied for foreach()

I'm adding oneToMany relationship to database, and its working but when i want to view array i get this error :
Warning: Invalid argument supplied for foreach()
this is my User.php
class User implements AdvancedUserInterface, \Serializable
{
// ...
/**
* #ORM\OneToMany(targetEntity="Acme\CityBundle\Entity\City", mappedBy="user")
**/
private $cities;
public function __construct()
{
$this->cities = new ArrayCollection();
}
/**
* #inheritDoc
*/
public function getCities()
{
$c = array();
foreach ($this->cities as $city) {
$c[] = $city->getCity();
}
return $c;
}
/**
* Add cities
*
* #param \Acme\CityBundle\Entity\City $cities
* #return User
*/
public function addCity(\Acme\CityBundle\Entity\City $city)
{
$city->setUser($this);
$this->cities->add($city);
return $this->cities;
}
and City.php
<?php
namespace Acme\CityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* City
*/
class City
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $name;
/**
* #ManyToOne(targetEntity="Acme\UserBundle\Entity\User", inversedBy="cities")
* #JoinColumn(name="id", referencedColumnName="id")
**/
private $user;
public function setUser($user)
{
$this->user = $user;
return $this;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return City
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
public function getCity()
{
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
}
Controller
$city=new City();
$em = $this->getDoctrine()->getManager();
$city->setName('Miasto');
$user->addCity($city);
$em->persist($city);
$em->persist($user);
$em->flush();
index controller
public function indexAction()
{
$cities=$this->get('security.context')->getToken()->getUser()->getCities();
return $this->render(
'AcmeUserBundle:User:index.html.twig',array( 'cities'=>$cities));
}
and when i try to show array (cities) in view i get error
Warning: Invalid argument supplied for foreach()
in User.php
foreach ($this->cities as $city)
my table city look (id,name)
Thanks for any help.
EDIT : SOLVED
I have to update my CityBundle\Resources\config\doctrine\City.orm.yml file
In your City class, shouldn't be the relationship something like :
/**
* #ManyToOne(targetEntity="Acme\UserBundle\Entity\User", inversedBy="cities")
* #JoinColumn(name="cityId", referencedColumnName="id")
**/
private $user;
The join column shouldn't be the id of user's table.
And then, of course:
public function getCities()
{
return $this->cities;
}

Resources