I implemented a manyToMany relationship in Symfony2/Doctrine, where the relation is an Entity itself (that was necessary because I needed to add additional columns - notice that these additional columns are not mentioned below).
There are a couple of Q&As around here that recommend to take the relationship as an entity (e.g. here, here, here or here).
I have automatically generated all getter and setter methods via doctrine:generate:entities
(this explains why it is called addCompanie
instead of addCompany
), so I would have thought that this covers my oneToMany/ManyToOne relationship.
And creating a User and a Company work fine so far. But as soon as I try to assign a user to a company I get the following error message:
Found entity of type Acme\MyBundle\Entity\User on association Acme\MyBundle\Entity\Company#employees, but expecting Acme\MyBundle\Entity\CompanyHasUser
These are my Doctrine definitions (yml):
# User
Acme\MyBundle\Entity\User:
type: entity
fields:
id:
id: true
type: integer
generator:
strategy: AUTO
oneToMany:
companies:
targetEntity: Acme\MyBundle\Entity\CompanyHasUser
mappedBy: employees
# Company
Acme\MyBundle\Entity\Company:
type: entity
fields:
id:
id: true
type: integer
generator:
strategy: AUTO
oneToMany:
employees:
targetEntity: Acme\MyBundle\Entity\CompanyHasUser
mappedBy: companies
# CompanyHasUser
Acme\MyBundle\Entity\CompanyHasUser:
type: entity
fields:
id:
id: true
type: integer
generator:
strategy: AUTO
manyToOne:
companies:
targetEntity: Acme\MyBundle\Entity\Company
inversedBy: employees
joinColumns:
company_id:
referencedColumnName: id
nullable: false
employees:
targetEntity: Acme\MyBundle\Entity\User
inversedBy: companies
joinColumns:
user_id:
referencedColumnName: id
nullable: false
This is what my Entity class User look like
namespace Acme\MyBundle\Entity;
class User
{
private $id;
private $companies;
public function __construct()
{
$this->companies = new \Doctrine\Common\Collections\ArrayCollection();
}
public function addCompany(\Acme\MyBundle\Entity\CompanyHasUser $companies)
{
$this->companies[] = $companies;
return $this;
}
public function removeCompany(\Acme\MyBundle\Entity\CompanyHasUser $companies)
{
$this->companies->removeElement($companies);
}
public function getCompanies()
{
return $this->companies;
}
}
This is what my Entity class Company look like
namespace Acme\MyBundle\Entity;
class Company
{
private $id;
private $employees;
public function __construct($name, $companyAdmin)
{
$this->employees = new \Doctrine\Common\Collections\ArrayCollection();
}
public function addEmployee(\Acme\MyBundle\Entity\CompanyHasUser $employees)
{
$this->employees[] = $employees;
return $this;
}
public function removeEmployee(\Acme\MyBundle\Entity\CompanyHasUser $employees)
{
$this->employees->removeElement($employees);
}
public function getEmployees()
{
return $this->employees;
}
}
And this is what my Entity class CompanyHasUser looks like (relation between User
and Company
, but as far as this relation contains further columns - not mentioned in these code snippets - I had to create it as an Entity):
namespace Acme\MyBundle\Entity;
class CompanyHasUser
{
private $companies;
private $employees;
public function setCompanies(\Acme\MyBundle\Entity\Company $companies)
{
$this->companies = $companies;
return $this;
}
public function getCompanies()
{
return $this->companies;
}
public function setEmployees(\Acme\MyBundle\Entity\User $employees)
{
$this->employees = $employees;
return $this;
}
public function getEmployees()
{
return $this->employees;
}
}
My Controller logic is:
// Create new User (employee)
$user = new User();
$em = $this->getDoctrine()->getManager();
$em->persist($user);
// Create new Company (employer)
$company = new Company();
// Create relationship
$company->addEmployee($user);
$em->persist($company);
// Flush
$em->flush();