I have a GAME table and a SPELL table.
In my game table, I have two spells from the spell table.
//SPELL TABLE
/**
* #ORM\OneToMany(targetEntity="Game", mappedBy="spell")
*/
protected $game;
public function __construct()
{
$this->game = new ArrayCollection();
}
//GAME TABLE
/**
* #ORM\ManyToOne(targetEntity="Spell", inversedBy="game")
* #ORM\JoinColumn(name="spell1", referencedColumnName="id")
*/
protected $spell1;
/**
* #ORM\ManyToOne(targetEntity="Spell", inversedBy="game")
* #ORM\JoinColumn(name="spell2", referencedColumnName="id")
*/
protected $spell2;
In my Symfony2 Profiler I get these messages.
"AppBundle\Entity\Game":
The mappings AppBundle\Entity\Game#spell1 and AppBundle\Entity\Spell#game are inconsistent with each other.
The mappings AppBundle\Entity\Game#spell2 and AppBundle\Entity\Spell#game are inconsistent with each other.
Are these the wrong relations?
Related
I've setup Doctrine and Symfony-forms independent of the Symfony Framework (as I don't need most of it).
The issue I'm having is, when trying to persist a new "Audit" which has an "Type" doctrine seems to want to persist the owning side of the relationship (Type).
For example as Audit may have a type of Vehicle Service.
// -- Model/Audit.php --
/**
* #var \Model\Type
*
* #ORM\ManyToOne(targetEntity="Model\Audit\Type", inversedBy="audits")
* #ORM\JoinColumn(name="type_id", referencedColumnName="id", nullable=true)
*/
private $type;
/**
* Set type
*
* #param \Model\Type $type
* #return Audit
*/
public function setType(\Model\Type $type)
{
$this->type = $type;
return $this;
}
And then in the inverse side:
/**
* #ORM\OneToMany(targetEntity="Model\Audit", mappedBy="type")
* #var type */
private $audits;
public function __construct() {
$this->audits = new \Doctrine\Common\Collections\ArrayCollection();
}
Persistance code looks as follows:
$data = $form->getData();
$entityManager->persist($data);
$entityManager->flush();
And finally the form class is:
class AuditType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name')
->add('type', 'entity', array(
'class' => "Model\Type"
));
}
All looks (to me at least) exactly the same as in all the documentations both Doctrine and Symfony sides but I'm getting this error:
A new entity was found through the relationship 'Model\Audit#type'
that was not configured to cascade persist operations for entity:
Vehicle Service. To solve this issue: Either explicitly call
EntityManager#persist() on this unknown entity or configure cascade
persist this association in the mapping for example
#ManyToOne(..,cascade={"persist"})."
Which is really frustrating as I don't want to persist the Type side, I just want to put (in most basic terms) the id of 3 into the type_id column. Yet Doctrine seems to think I want to create a new "Type" which I certainly do not. They already exist.
Using $entityManager->merge($audit); works in part, it allows the inital Audit and its FK's to be saved. However it caused any embedded forms to become ignored.
I think you need set
/**
* #ORM\OneToMany(targetEntity="Model\Audit", mappedBy="type")
* #var type
*/
private $audits;
public function __construct() {
$this->audits = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #return ArrayCollection
*/
public function getAudits()
{
return $this->audits;
}
/**
* #param Audit $audit
*/
public function addAudits(Audit $audit)
{
$this->audits->add($audit);
$audit->setTyoe($this);
}
and in Type Audit.model
// -- Model/Audit.php --
/**
* #var \Model\Type
*
* #ORM\ManyToOne(targetEntity="Model\Audit\Type", inversedBy="audits")
* #ORM\JoinColumn(name="type_id", referencedColumnName="id", nullable=true)
*/
private $type;
/**
* Set type
*
* #param \Model\Type $type
* #return Audit
*/
public function setType(\Model\Type $type)
{
$this->type = $type;
}
I want to be able to select a school (that has its own entity) while creating a mission (also has its entity)
Since a school can have several missions, and you can select several schools at the mission's creation, I used a ManyToMany.
The problem is that after creating this "ManyToMany", generating the entities and updating my schema, Symfony created a table, but left it totally empty, without the two columns that I asked for. I'm not really used to Symfony nor to the ManyToMany system, so I might have done some mistake without noticing it, still I find this weird.
Here's the interesting part of my ecole (school) entity:
class Ecole{
// ...
/**
* #ORM\ManyToMany(targetEntity="MissionBundle\Entity\Mission", mappedBy="ecolesDispo")
*/
protected $missionsDispos;
// ...
/**
* Add missionsDispo
*
* #param \MissionBundle\Entity\Mission $missionsDispo
*
* #return Ecole
*/
public function addMissionsDispo(\MissionBundle\Entity\Mission $missionsDispo)
{
$this->missionsDispos[] = $missionsDispo;
return $this;
}
/**
* Remove missionsDispo
*
* #param \MissionBundle\Entity\Mission $missionsDispo
*/
public function removeMissionsDispo(\MissionBundle\Entity\Mission $missionsDispo)
{
$this->missionsDispos->removeElement($missionsDispo);
}
/**
* Get missionsDispos
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getMissionsDispos()
{
return $this->missionsDispos;
}
And here is the interesting part of my mission entity:
/**
* #ORM\ManyToMany(targetEntity="EcoleBundle\Entity\Ecole", inversedBy="missionsDispo")
* #ORM\JoinTable(name="Mission2Ecole",
* joinColumns={#ORM\JoinColumn(name="em_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="me_id", referencedColumnName="id")}
* )
*/
protected $ecolesDispo;
// ...
/**
* Constructor
*/
public function __construct()
{
$this->ecolesDispo = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add ecolesDispo
*
* #param \EcoleBundle\Entity\Ecole $ecolesDispo
*
* #return Mission
*/
public function addEcolesDispo(\EcoleBundle\Entity\Ecole $ecolesDispo)
{
$this->ecolesDispo[] = $ecolesDispo;
return $this;
}
/**
* Remove ecolesDispo
*
* #param \EcoleBundle\Entity\Ecole $ecolesDispo
*/
public function removeEcolesDispo(\EcoleBundle\Entity\Ecole $ecolesDispo)
{
$this->ecolesDispo->removeElement($ecolesDispo);
}
/**
* Get ecolesDispo
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getEcolesDispo()
{
return $this->ecolesDispo;
}
After all this was created, I was supposed to get a multi selector with the list of all the schools saved in the database (I already added it to the missionType file), but I get absolutely nothing.
I don't really know if I inverted the annotations, or if the "joinTable" part is correct, but I'm completely lost here.
Does anyone have an idea?
Thank you in advance
Just wrong typo "s"? inversedBy="missionsDispo" >>> inversedBy="missionsDispos"
PS. Official doc here
http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/association-mapping.html#many-to-many-bidirectional
I have a page address.html.twig , the user can add many addresses in the table UserAddress. when he added his address in the database , the address should be render in the same page that he added his address then he can choose which one he would like to use. Unfortunately the address is not render.
First i thought that i have a problem in my controller action or in my twig page. I even asked a question here about it => here
I verified all my tables in phpmyadmin and all of them are well link but if i'm doing this: php app/console doctrine:schema:validate
i have this error :
[Mapping] FAIL - The entity-class
'FLY\BookingsBundle\Entity\Commandes' mapping is invalid:
* The association FLY\BookingsBundle\Entity\Commandes#user refers to the inverse side field
Application\Sonata\UserBundle\Entity\User#commandes which does not
exist.
[Mapping] FAIL - The entity-class
'FLY\BookingsBundle\Entity\UserAddress' mapping is invalid:
* The association FLY\BookingsBundle\Entity\UserAddress#user refers to the inverse side field
Application\Sonata\UserBundle\Entity\User#address which does not
exist.
Have a look at this picture:
This is my UserAddress.php
/**
* #ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User", inversedBy="address")
* #ORM\JoinColumn(nullable=true)
*/
private $user;
Commandes.php
/**
* #ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User", inversedBy="commandes")
* #ORM\JoinColumn(nullable=true)
*/
private $user;
User.php
/**
* #ORM\Entity(repositoryClass="FLY\UserBundle\Repository\UserRepository")
* #ORM\Table(name="fos_user_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
public function __construct()
{
parent::__construct();
$this->commandes = new \Doctrine\Common\Collections\ArrayCollection();
$this->address = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #ORM\OneToMany(targetEntity="FLY\BookingsBundle\Entity\Commandes", mappedBy="user", cascade={"remove"})
* #ORM\JoinColumn(nullable=true)
*/
private $commandes;
/**
* #ORM\OneToMany(targetEntity="FLY\BookingsBundle\Entity\UserAddress", mappedBy="user", cascade={"remove"})
* #ORM\JoinColumn(nullable=true)
*/
private $address;
Here you can see my var dump:
User {#124 ▼
#id: 21
-commandes: null
-address: null
}
I've had an issue which has popped up 2-3 times in the last few years, where the mappings were incorrect but the schema update was successful. After the mappings were fixed this wasn't reflected in the schema and symfony assumed it was already up-to-date.
I recommend you try removing the relevent relationships manually from your user, commande and address tables and then run:
php app/console doctrine:schema:update --force
- it may fix your issue.
Heres an example from one of my apps - I've done this for your commandes entity.
You'll be able to piece together your UserAddress Entity from this example yourself!
Here goes:
User.php
/**
* #ORM\OneToMany(targetEntity="FLY\BookingsBundle\Entity\Commandes", mappedBy="commandesUser")
*/
protected $commandes;
User.php - Getters and Setters
/**
* Add commandes
*
* #param FLY\BookingsBundle\Entity\Commandes $commandes
*/
public function addCommandes(\FLY\BookingsBundle\Entity\Commandes $commandes)
{
$this->commandes[] = $commandes;
}
/**
* Get commandes
*
* #return Doctrine\Common\Collections\Collection
*/
public function getCommandes()
{
return $this->commandes;
}
Commandes.php
/**
* #ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User", inversedBy="commandes")
* #ORM\JoinColumn(name="user", referencedColumnName="id")
*/
private $commandesUser;
Commandes.php - Getters and Setters
/**
* Set commandesUser
*
* #param Application\Sonata\UserBundle\Entity\User $commandesUser
*/
public function setCommandesUser(\Application\Sonata\UserBundle\Entity\User $commandesUser = null)
{
$this->commandesUser = $commandesUser;
}
/**
* Get $commandesUser
*
* #return Application\Sonata\UserBundle\Entity\User
*/
public function getCommandesUser()
{
return $this->commandesUser;
}
It's quite likely this doesn't happen to anyone else, but there's a chance.
In my case, this error appeared because there was a duplicate. My entity had 2 fields, which are ManyToOne relationships. And they both had the same inversed names, which gave this error.
So this is the relevant bit of code:
class TaskIngredient
{
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Ingredient", inversedBy="taskIngredients")
* #ORM\JoinColumn(nullable=false)
*/
private $ingredient;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Task", inversedBy="taskIngredients")
* #ORM\JoinColumn(nullable=false)
*/
private $task;
}
The solution was relatively easy. I tried changing the inversedBy name, manually. However this didn't fix it (even after applying php app/console doctrine:schema:update --force and removing the var/cache folder).
So I just:
Removed one of the problematic entities (and it's setter/getter)
Ran the php bin/console make:entity tool and readded the field with a different name
Voilà! Issue fixed.
I've a ManyToMany relationship between Pais and FabricanteDistribuidor tables defined as follow:
Pais.php
class Pais
{
// column definitions
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\FabricanteDistribuidor", inversedBy="paises", cascade={"persist"})
* #ORM\JoinTable(name="negocio.fabricante_distribuidor_pais", schema="negocio",
* joinColumns={#ORM\JoinColumn(name="fabricante_distribuidor_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="pais_id", referencedColumnName="id")}
* )
*/
protected $fabricanteDistribuidor;
/**
* Add fabricanteDistribuidor
*
* #param AppBundle\Entity\FabricanteDistribuidor $fabricanteDistribuidor
*/
public function addfabricanteDistribuidor(\AppBundle\Entity\FabricanteDistribuidor $fabricanteDistribuidor)
{
$this->fabricanteDistribuidor[] = $fabricanteDistribuidor;
}
/**
* Get fabricanteDistribuidor
*
* #return Doctrine\Common\Collections\Collection
*/
public function getfabricanteDistribuidor()
{
return $this->fabricanteDistribuidor;
}
}
FabricanteDistribuidor.php
class FabricanteDistribuidor
{
// column definitions
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Pais", mappedBy="fabricanteDistribuidor", cascade={"persist"})
*/
protected $paises;
public function __construct()
{
$this->paises = new ArrayCollection();
}
/**
* Set paises
*
* #param AppBundle\Entity\Pais $pais
* #return FabricanteDistribuidor
*/
public function addPaises(\AppBundle\Entity\Pais $pais)
{
$this->paises[] = $pais;
return $this;
}
/**
* Get paises
*
* #return Doctrine\Common\Collections\Collection
*/
public function getPaises()
{
return $this->paises;
}
}
That will generate a table fabricante_distribuidor_pais on the schema negocio with fabricante_distribuidor_id and pais_id FK pointing to the PK on the related tables, that's fine.
Regarding this scenario:
1- It's possible to define fabricante_distribuidor_id and pais_id as PK on the fabricante_distribuidor_pais table? I mean adding some extra annotation or I need to create a external entity and set them as #ORM\Id on the column definition?
2- Are the addXXX and getXXX methods right in my entities? By right I mean: I should add one or many paises (from Pais entity) to FabricanteDistribuidor easily and I don't care about to the inverse relation meaning I will not add FabricanteDistribuidor from a Pais, are them right or do I need to change something?
1- If one id is a primary key doesn't the relation becomes many to one/ one to many ? Even 1to1 if both are PK
2- If you don't care about the inverse you are going to add getters and setters in only one entity yes. You can still change it to a biredictionnal later with the attribute "mappedBy"
Check if an entity exists :
You can do that in your controller :
for example in Pays
$data = $em->getRepository('AcmeBundle:Pais')->findOneByFabricanteDistribuidor($id);
if($data)
{
// the entity is allready persisted
}
else
{
// no, we can persist the entity
}
I have three types of entities,
Users
Groups
Websites
Users can have Websites, and they also can belong to Groups
Each of these entities has a name as well.
Here are my Doctrine2 definitions:
<?php
/** #Entity */
class User
{
// ...
/**
* #Column(type="string",length=255,nullable=false)
* #var string
*/
protected $name;
/**
* #ManyToMany(targetEntity="Group", inversedBy="users")
* #JoinTable(name="users_groups")
*/
private $groups;
/**
* #ManyToMany(targetEntity="Website", inversedBy="users")
* #JoinTable(name="users_websites")
*/
private $websites;
// ...
}
/** #Entity */
class Group
{
// ...
/**
* #Column(type="string",length=255,nullable=false)
* #var string
*/
protected $name;
/**
* #ManyToMany(targetEntity="User", mappedBy="groups")
*/
private $users;
// ...
}
/** #Entity */
class Website
{
// ...
/**
* #Column(type="string",length=255,nullable=false)
* #var string
*/
protected $name;
/**
* #ManyToMany(targetEntity="User", mappedBy="websites")
*/
private $users;
// ...
}
So now if I want to find all Users in a group called "Admins", I can do this:
$group = $em->getRepository("Group")->findOneByName("Admins");
$users = $group->users;
I can also get all users that are associated with website "Google.com" by doing:
$websites = $em->getRepository("Website")->findOneByName("Google.com");
$users = $websites->users;
Now if I want to get all users who are in "Admins", and are also associated with website "Google", what can I do?
If I was using TSQL, I would join the three tables, how do I do that in Doctrine?
Must I use DQL? How would the DQL look like?
You should use DQL for this.
SELECT u
FROM User u
JOIN u.groups g
JOIN u.websites w
WHERE
g.name = :group_name
AND w.name = :website_name
And the php code to do so:
$dql = '...'; // What i've written above
$query = $em->createQuery($dql);
$query->setParameter('group_name', 'Admins');
$query->setParameter('website_name', 'Google');
$users = $query->getResult();
I encourage you to read the doctrine ORM DQL documentation : http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html
PS: The 2 lines of code you've written, should return groups, and websites, and not users