I am heaving some headache about this and I don't find the solution.
I have 2 entities: Movie.php and Category.php
I want one Movie to have multiple Categories and vice versa. That's why I chose a ManyToMany relationship.
Now I am wondering... What happens on the database site? Is there a "in-between" table that maps movie_ids to category_ids? But that's not what happened. Actually my first try was to make a MovieCategory entity - I mapped one movie to multiple categories with OneToMany and in the MovieCategory entity I made a OneToOne connection to get the category name from my Category entity. But I guess that's not how it should work, am I right?
Now here's my code of how i think it should work, I really appreciate any help I can get on this:
Movie.php
<?php
/**
* #ORM\Table(name="movies")
* #ORM\HasLifecycleCallbacks()
*/
class Movie
{
public function __construct()
{
$this->categories = new ArrayCollection();
}
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/** #ORM\Column(type="string") */
protected $moviename;
/**
* #ORM\ManyToMany(targetEntity="Category", mappedBy="movie")
*/
protected $categories;
}
Category.php
<?php
/**
* #ORM\Table(name="categories")
* #ORM\HasLifecycleCallbacks()
*/
class Category
{
public function __construct()
{
$this->movies = new ArrayCollection();
}
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string")
*/
protected $name;
// ...
/**
* #ORM\ManyToMany(targetEntity="Movie", mappedBy="movie", cascade={"persist"})
*/
protected $movies;
}
According to Doctrine docs it should look this way:
// Movie.php
/**
* #ORM\ManyToMany(targetEntity="Category", inversedBy="movies")
* #ORM\JoinTable(name="movies_categories")
*/
protected $categories;
// ...
// Category.php
/**
* #ORM\ManyToMany(targetEntity="Movie", mappedBy="categories")
*/
protected $movies;
You're using the same value for mappedBy in both declarations. Plus, the value you use is singular, it should be plural. This cannot work.
Related
I want to ultimately have an abstract base class that defines a relationship to another entity for all inheriting Entity-classes. So have this test-setup that was created with symfony's make:entity-command.
The only thing I changed was switching the MappedSuperClass's property-visibility from private to protected to make them visible to the extenders.
This is the MappedSuperClass:
[...]
/**
* Class TestMappedSuperclass
*
* #package App\Entity
* #ORM\MappedSuperclass()
*/
class TestMappedSuperclass
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity=TestTarget::class, mappedBy="testMappedSuperclass")
*/
protected $targets;
public function __construct()
{
$this->targets = new ArrayCollection();
}
//..getters/setters,add/remove...
}
This my target-entity for the mapping:
[...]
/**
* #ORM\Entity(repositoryClass=TestTargetRepository::class)
*/
class TestTarget
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity=TestMappedSuperclass::class, inversedBy="targets")
*/
private $testMappedSuperclass;
// ..getters,setters..
}
This is the extending entity class:
[...]
/**
* #ORM\Entity(repositoryClass=TestEntityRepository::class)
*/
class TestEntity extends TestMappedSuperclass
{
}
So when I try to do a make:migration it produces the following error:
Column name `id` referenced for relation from App\Entity\TestTarget towards
App\Entity\TestMappedSuperclass does not exist.
Using: Symfony 5.1, Doctrine 2.7
AFAIK you need to have repeat id as protected in TestEntity :
/**
* #ORM\Entity(repositoryClass=TestEntityRepository::class)
*/
class TestEntity extends TestMappedSuperclass
{
/**
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
}
I took this from a project where i´m using mappedSuperClass like this, i´m not relate entities in it though
I'm trying to create an entity that is connected with another entity 1:1. The whole point is that Equip has to have an Estadi, and just one. I can update the schema correctly, the database is okay, but on the webpage debugger appears a mapping error.
The association AppBundle\Entity\Equip#estadi refers to the inverse
side field AppBundle\Entity\Estadi#nom which is not defined as
association.
The association AppBundle\Entity\Equip#estadi refers to the inverse
side field AppBundle\Entity\Estadi#nom which does not exist
This is entity Estadi:
/**
* #ORM\Entity
* #ORM\Table(name="estadis")
*/
class Estadi{
/**
* #ORM\Column(type="string",length=30)
* #ORM\OneToOne(targetEntity="Equip",mappedBy="estadi",cascade={"persist"})
* #ORM\Id
*/
protected $nom;
/**
* #ORM\Column(type="integer")
*/
protected $aforament;
/**
* #ORM\Column(type="integer")
*/
protected $num_portes;
/**
* #ORM\Column(type="string",length=50)
*/
protected $direccio;
/**
* #ORM\Column(type="string", length=4)
*/
protected $any_construccio;
/**
* #ORM\Column(type="string", length=30)
*/
protected $nom_aficio;
}
This is Entity Equip:
/**
* #ORM\Entity
* #ORM\Table(name="equips")
*/
class Equip{
/**
* #ORM\Column(type="string",length=30)
* #ORM\Id
*/
protected $nom;
/**
* #ORM\Column(type="integer")
*/
protected $punts_lliga;
/**
* #ORM\Column(type="integer")
*/
protected $num_jugadors;
/**
* #ORM\OneToOne(targetEntity="Estadi",inversedBy="nom")
* #ORM\JoinColumn(name="nom_estadi",referencedColumnName="nom",onDelete="SET NULL")
*/
protected $estadi;
/**
* #ORM\OneToOne(targetEntity="Entrenador",inversedBy="nom")
* #ORM\JoinColumn(name="nom_entrenador",referencedColumnName="nom",onDelete="SET NULL")
*/
protected $entrenador;
/**
* #ORM\ManyToOne(targetEntity="Lliga",inversedBy="equips")
* #ORM\JoinColumn(name="nom_lliga",referencedColumnName="nom",onDelete="SET NULL")
*/
protected $lliga;
/**
* #ORM\OneToMany(targetEntity="Jugador",mappedBy="nom_equip")
*/
protected $jugadors;
public function __construct(){
$this->jugadors = new ArrayCollection();
}
}
When you define the #OneToOne annotation, it should not be on your primary key. Either the owning entity should contain a single association (unidirectional), or each entity should contain an association to the other - as entities, not connected to a primary key.
Your Equip mapping should instead look like this:
/**
* #ORM\OneToOne(targetEntity="Estadi", inversedBy="equip")
* #ORM\JoinColumn(name="nom_estadi", referencedColumnName="nom")
*/
protected $estadi;
public function setEstadi(Estadi $estadi)
{
$this->estadi = $estadi;
return $this;
}
public function getEstadi()
{
return $this->estadi;
}
Your Estadi mapping should instead look like this:
/**
* #OneToOne(targetEntity="Equip", mappedBy="estadi")
*/
protected $equip;
public function getEquip(Equip $equip)
{
return $this->equip;
}
I removed the cascade and onDelete, because if you're handling everything through Doctrine it should handle that for you automatically, but you still might have a use for them. I also only put the setter on the owning entity from the way you described, but you could put it back on your Estadi entity as well - that's up to you.
I'm trying to setup a many to many between fos Userbundle and my own group bundle so that I can group users. this is working fine. I can set a new group and can add as many users to this group as I like to. But when I want to check if a user is in a group, I get a Index join Column error. I think I didn't understand the usage of manytomany the correct way so it would be nice if you can help me getting the point.
My entities look like:
User:
class User extends BaseUser
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
protected $usergroups;
//....//
And my Group Entity looks like:
/**
* #ORM\ManyToMany(targetEntity="PrUserBundle\Entity\User", inversedBy="id")
* #ORM\JoinColumn(name="id", referencedColumnName="id")
* #var user
*/
private $user;
//....
/**
* Add user
*
* #param \PrUserBundle\Entity\User $user
* #return Lieferanten
*/
public function addUser(\PrUserBundle\Entity\User $user)
{
$this->user[] = $user;
return $this;
}
/**
* Remove user
*
* #param \PrUserBundle\Entity\User $user
*/
public function removeUser(\PrUserBundle\Entity\User $user)
{
$this->user->removeElement($user);
}
/**
* Get user
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUser()
{
return $this->user;
}
When I try to catch all users in a group, I get an error:
$group=$em->getRepository('PrGroupBundle:Group')->findAll();
var_dump($lfr[0]->getUser()->getId());
I guess I missunderstood how to handle the bidirectional manytomany. Or can I use a manytoone also?
in my database, i got this
table data
----------
id
name
description
image1
image2
image3
key
...
and my entity Media from SonataMediaBundle, i want to put the images in the entity Media Manager of SonataMediaBundle
How in my entity write the properties for images ?
What kind of realtion is ?
thx for your help
This is simply 3 times a ManyToOne relation to (probably) an Image entity.
The entity would look like following:
class Item
{
/**
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\Column(type="string")
*/
protected $name;
/**
* #ORM\Column(type="text")
*/
protected $description;
/**
* #ORM\ManyToOne(targetEntity="YourNamespace\Entity\Image")
*/
protected $image1;
/**
* #ORM\ManyToOne(targetEntity="YourNamespace\Entity\Image")
*/
protected $image2;
/**
* #ORM\ManyToOne(targetEntity="YourNamespace\Entity\Image")
*/
protected $image3;
/**
* #ORM\Column(type="string")
*/
protected $key;
// ...
}
I have many relations of this type, but I can't see why this one is not working.
I have a Delegation and a Promotion entities:
Delegation
Promotion
/**
* Company\CBundle\Entity\Promotion
*
* #ORM\Entity
* #DoctrineAssert\UniqueEntity("promotionCode")
*/
class Promotion
{
const REGISTER_DAYS = 30;
const REGISTER_DISCOUNT = 100;
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="promotionCode", type="string", unique=true, nullable=true)
*/
protected $promotionCode;
/**
* #ORM\Column(name="name", type="string")
*/
protected $name;
/**
* #ORM\Column(name="description", type="string", nullable=true)
*/
protected $description;
/**
* #ORM\Column(name="days", type="integer")
*/
protected $days;
/**
* #ORM\Column(name="discount", type="float")
*/
protected $discount;
/**
* #ORM\ManyToOne(targetEntity="Delegation", inversedBy="promotions")
* #ORM\JoinColumn(name="delegation_id", referencedColumnName="id")
*/
private $delegation;
/**
* #ORM\ManyToOne(targetEntity="Product", inversedBy="promotions")
*/
private $product;
/**
* #var date $adquiredDate
*
* #ORM\Column(name="adquiredDate", type="date", nullable=true)
*/
private $adquiredDate;
When in a controller I create a promotion, the table Promotion has the new object related to the delegation one
private function createPromotion($delegation)
{
$em = $this->getDoctrine()->getEntityManager();
$promotion = Promotion::createPromotion($delegacion, Promotion::REGISTER_DAYS, Promotion::REGISTER_DISCOUNT);
$em->persist($promotion);
$em->persist($delegation);
$em->flush();
}
Database
*************************** 15. row ***************************
id: 32
delegation_id: 19
days: 20
discount: 50
adquiredDate: 2013-01-10
*************************** 16. row ***************************
id: 33
delegation_id: 19
days: 25
discount: 50
adquiredDate: 2013-01-10
*************************** 17. row ***************************
id: 34
delegation_id: 19
days: 30
discount: 50
adquiredDate: 2013-01-10
But when I call the $delegation->getPromotions() in another controller/action there is no promotions, returns a Doctrine\ORM\PersistentCollection with no data.
Can anyone help, please?
Edit with more information.
$delegation->getPromotions() is empty, but looking for a promotion of that delegation and calling $promotion->getDelegation() is returning the delegation correctly :?
Have you tried defining your $delegation property like
/**
* #ORM\ManyToOne(targetEntity="Delegation", inversedBy="promotions")
* #ORM\JoinColumn(name="delegation_id", referencedColumnName="id")
*/
private $delegation;
See Doctrine2 Docs: Association Mapping->Many-To-One
Also there are a lot of typos in your code. For example
/**
* #ORM\OneToMany(targetEntity="Promotion", mappedBy="delegacion", cascade={"all"}, orphanRemoval=true)
*/
protected $promotions;
mappedBy="delegacion" should be mappedBy="delegation".
Or
public function getDeleTacion()
{
return $this->deleTacion;
}
Should be
public function getDelegation()
{
return $this->delegation;
}
Edit
Okay, I created a minimalistic version for you that worked for me. You can built it up from there or watch for differences with your code:
Promotion.php
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class Promotion
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Delegation", inversedBy="promotions", cascade={"persist"})
* #ORM\JoinColumn(name="delegation_id", referencedColumnName="id")
*/
public $delegation;
/**
* #ORM\ManyToOne(targetEntity="Product", inversedBy="promotions", cascade={"persist"})
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
public $product;
}
Delegation.php
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class Delegation
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="Promotion", mappedBy="delegation", cascade={"all"}, orphanRemoval=true)
*/
public $promotions;
public function __construct() {
$this->promotions = new \Doctrine\Common\Collections\ArrayCollection();
}
}
Product.php
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class Product
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="Promotion", mappedBy="product", cascade={"all"}, orphanRemoval=true)
*/
public $promotions;
public function __construct() {
$this->promotions = new \Doctrine\Common\Collections\ArrayCollection();
}
}
If you now do something like
$delegation = new Delegation();
$product = new Product();
$promotion = new Promotion();
$promotion->delegation = $delegation;
$promotion->product = $product;
$em->persist($promotion);
$em->flush();
$products = $em->createQuery('select p from BundleName\Entity\Product p')->execute();
$delegations = $em->createQuery('select d from BundleName\Entity\Delegation d')->execute();
var_dump(count($products[0]->promotions), count($delegations[0]->promotions));
You should end up with
int(1)
int(1)
So the refrence is in fact saved and can be read. Phew. Good luck with that! :-)
I had a similar error where my many-to-one relationship on some freshly created entities contained entities, and an inverse one-to-many didn't, although database clearly had the corresponding rows in it.
I did persist and flush entities on the one-to-many side, but I had to also do
$entityManager->clear();
before getting those entities from a repository again for the one-to-many relationship to be able to access those entities.