Reputation: 177
I have two simple entities. One is for services, and one that contains products. Many services can have many products.
For example, service1 is composed from product2 and product6, service2 is composed from product1 and product2, ...
I've created the products entity (id and name), and then created the service entity with id, name and:
/**
* @var ArrayCollection
*
* @ORM\ManyToMany(targetEntity="Product", cascade={"persist", "remove"}, mappedBy="service")
*/
private $products;
But this only generate two real tables, one called service and one called product. And service table even don't have a field called products.
I think that this must create another table called service_product to store the relationship between the two tables.
What's wrong ?
Upvotes: 0
Views: 376
Reputation: 758
If you only define the relationship like this and do nothing else in the product entity it's not gonna work. What you have defined here is only the inverse side because of the
mappedBy="service"
To define the owning side of the relation you need to use
inversedBy
Also I suppose that the property in the Product entity is named services and not service like what you have in the mappedBy.
UPDATE:
Here is a code that works perfectly on my side. I created the Product
and Service
entities in the console with the generator, then only added the ManyToMany
line in the Service entity. When I did a doctrine:schema:update --force
, 3 tables were created: Product, Service and service_product.
The Product entity:
<?php
namespace Test\TestBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Product
*
* @ORM\Table()
* @ORM\Entity
*/
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;
/**
* 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;
}
}
And the Service entity:
<?php
namespace Test\TestBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Service
*
* @ORM\Table()
* @ORM\Entity
*/
class Service
{
/**
* @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;
/**
* @ORM\ManyToMany(targetEntity="Product", cascade={"persist", "remove"})
*/
private $products;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return Service
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
}
These are very basics entities. You should also add a getter and a setter in the Service entity for the products property, and probably declare the products as an ArrayCollection in the constructor.
Upvotes: 1
Reputation: 4397
Make sure you have defined both side mappedBy
and inversedBy
in both entities
//Service.php (Service class)
/**
* @ORM\ManyToMany(targetEntity="Product", inversedBy="services", cascade={"persist", "remove"})
* @ORM\JoinTable(name="product_service_table_name")
*/
protected $products;
And
//Product.php (Product class)
/**
* @ORM\ManyToMany(targetEntity="Service", mappedBy="products", cascade={"persist", "remove"})
* @ORM\JoinTable(name="product_service_table_name")
*/
protected $services;
Just in case to have a specific name for the join table you can define it as mentioned in the source above but make sure the names should be equal
Upvotes: 0