Reputation: 857
I got 3 entities:
1st:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* ProactiveSubject
*
* @ORM\Table(name="ProactiveSubject")
* @ORM\Entity
*/
class ProactiveSubject
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="ProactiveCheck", inversedBy="p_subjects")
* @ORM\JoinTable(name="subject_check_operator")
*/
private $checks;
public function __construct() {
$this->checks = new \Doctrine\Common\Collections\ArrayCollection();
}
}
2nd:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* ProactiveCheck
*
* @ORM\Table(name="ProactiveCheck")
* @ORM\Entity
*/
class ProactiveCheck
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="ProactiveSubject", mappedBy="ProactiveChecks")
*/
private $p_subjects;
public function __construct() {
$this->p_subjects = new \Doctrine\Common\Collections\ArrayCollection();
}
}
and 3rd:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* ProactiveOperator
*
* @ORM\Table(name="ProactiveOperator")
* @ORM\Entity
*/
class ProactiveOperator
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="ProactiveSubject", inversedBy="p_subjects")
*
*/
private $p_operator;
public function __construct() {
$this->p_operator = new \Doctrine\Common\Collections\ArrayCollection();
}
}
In short, 1 subject may have many checks, and these checks may have many operators, so it should look like that:
subject1 ==> check EQUALITY ==> operator =
subject1 ==> check GREATER ==> operator >
subject2 ==> check AMOUNT ==> operator = or operator > or operator < etc... depending on user input
I need to make something like a a many_tomany_tomany connection in my db so 3 entities should be connected through 1 join table. The problem is that when I run doctrine:schema:update --force
, it connects only 2 entities (operator
and subject
), but does not connect a Check
entity. Any Ideas how to fix that and make a table subject_check_operator
with these entities? Any ideas would be welcome. Thank you.
Upvotes: 2
Views: 1645
Reputation: 171
It is fascinating question and answer is interesting too. If you're faced to the issue, it is mean that your vision and understanding of it is wrong. It is not ManuToMany. This will be another entity that will be responsible for this complex relation. Even if you somehow get away with it. Think about what you will do if you need the date of creating such relations.
<?php
namespace App\Entity;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class ChildrenFatherMotherMapping
{
#[ORM\Column(type: Types::INTEGER, nullable: false)]
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'IDENTITY')]
private int $id;
#[ORM\ManyToOne(inversedBy: 'childFatherMotherMappings')]
#[ORM\JoinColumn(nullable: false)]
private ?Child $child = null;
#[ORM\ManyToOne(inversedBy: 'childFatherMotherMappings')]
#[ORM\JoinColumn(nullable: false)]
private ?Father $father = null;
#[ORM\ManyToOne(inversedBy: 'childFatherMotherMappings')]
#[ORM\JoinColumn(nullable: false)]
private ?Mother $mother = null;
/** TODO: add getters and setters */
}
Upvotes: 0
Reputation: 2745
You have several issues here and to me it is not clear what your example with EQUALITY, GREATER, etc. means, but if this:
In short, 1 subject may have many checks, and these checks may have many operators, so it should look like that:
and
The problem is that when I run doctrine:schema:update --force, it connects only 2 entities (operator and subject), but does not connect a Check entity.
are your main issues here, than you need to fix your relational mapping, which contains several errors.
You need to decide wether you want the many-to-many relations to be bidirectional or unidirectional. For bidirectional relation please pay special attention to the documentation about owning and inversing sides of a relation
As you have already included mappedBy
and inversedBy
settings, I assume you aim for bidirectional relations. When working with bidirectional relations, you specify the attribute name for the mappedBy
and inversedBy
settings in the annotation and not the class names, etc.
ProactiveCheck
For the relation to subject mappedBy="ProactiveChecks"
should be mappedBy="checks"
. And you are missing the relation to the operator completely
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* ProactiveCheck
*
* @ORM\Table(name="ProactiveCheck")
* @ORM\Entity
*/
class ProactiveCheck
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="ProactiveSubject", mappedBy="checks")
*/
private $p_subjects;
/**
* @ORM\ManyToMany(targetEntity="ProactiveOperator", inversedBy="checks")
*/
private $operators;
public function __construct() {
$this->p_subjects = new \Doctrine\Common\Collections\ArrayCollection();
}
}
ProactiveOperator
If many checks should have many operators, this class is mapped wrong. You are creating a relation to ProactiveSubject
and have no relation to the ProactiveCheck
entity. That's why it is not connecting
when updating the database schema.
It should look like this:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* ProactiveOperator
*
* @ORM\Table(name="ProactiveOperator")
* @ORM\Entity
*/
class ProactiveOperator
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="ProactiveChecks", mappedBy="operators")
*
*/
private $p_operator;
public function __construct() {
$this->p_operator = new \Doctrine\Common\Collections\ArrayCollection();
}
}
By the way, you can easily check the validity of your mapping with the following command: bin/console doctrine:schema:validate
Upvotes: 1
Reputation: 893
So your trying to make an Entity-(many-to-many)-Entity-(many-to-many)-Entity
. This is no different than a single many to many. You were well on the way, however in your 3rd entity you sort of link to the first.
What you want is something (pseudo) like:
e1:
many-to-many: e2
e2:
many-to-many: e1
many-to-many: e3
e3:
many-to-many: e2
What your currently doing is pointing the reverse of e3 to the reverse of e1 (e2 > e1 property), so just make another property with its own many-to-many in e2 pointing to e3.
Just remember that each relation needs a property in the class if you want to access it.
This will however create two join tables. Which could be fine considering the situation. There is also another way where e2 is essentially the join table with some extra fields. Then you have a different situation and for that I would point you to Doctrine2: Best way to handle many-to-many with extra columns in reference table.
Upvotes: 0
Reputation: 1209
Maybe you can make an entity that will have the 3 relations you want (the equivalent of link table generated by doctrine, but custom)
Upvotes: 0