複雑な条件によってこのクエリを制限する問題追跡システムのテーブルで、いくつかの問題をクエリする必要があります。
問題(エンティティ)はカテゴリ(別のエンティティ)にグループ化されます。個人(エンティティ)は複数の役割(4番目のエンティティ)のメンバーであり、これは1つのManyToMany関係です。そして最後に、ロールは1つまたは複数のカテゴリにアクセスできます。これは、2番目のManyToMany関係です。
<?php
/**
* @Entity
* @Table(name="issue")
*/
class Issue
{
/**
* @ManyToOne(targetEntity="Category", fetch="EAGER")
* @JoinColumn(name="category", referencedColumnName="id", onDelete="RESTRICT", nullable=false)
*/
private $category;
…
}
/**
* @Entity
* @Table(name="category")
*/
class Category
{
/**
* @ManyToMany(targetEntity="Role", mappedBy="categories")
*/
private $roles;
…
}
/**
* @Entity
* @Table(name="role")
*/
class Role
{
/**
* @ManyToMany(targetEntity="Person", mappedBy="roles")
*/
private $persons;
/**
* @ManyToMany(targetEntity="Category", inversedBy="roles")
* @JoinTable(name="role_has_access_on_category",
* joinColumns={@JoinColumn(name="role_id", referencedColumnName="id")},
* inverseJoinColumns={@JoinColumn(name="category_id", referencedColumnName="id")}
* )
*/
private $categories;
…
}
/**
* @Entity
* @Table(name="person")
*/
class Person
{
/**
* @ManyToMany(targetEntity="Role", inversedBy="persons")
* @JoinTable(name="person_is_member_of_role",
* joinColumns={@JoinColumn(name="person_id", referencedColumnName="id")},
* inverseJoinColumns={@JoinColumn(name="role_id", referencedColumnName="id")})
*/
private $roles;
…
}
リレーションシップフィールドを除くすべてのフィールドを残しました。もちろん、主キーとさらに多くの列があります…</ p>
特定の主キーを持つユーザーがメンバーであるロールを介してアクセスできるカテゴリに属するすべての問題を取得したいと思います。
最初は、ManyToMany関係を照会する方法を実験し始めたばかりなので、以下のコードは実際には私のターゲットに似ていません。私はついに、クエリを取得して1つのManyToMany関係の反対側を取得する方法を見つけたので、人が属する役割をすでに取得できます。ただし、このクエリは、ロールがアクセスできるカテゴリをフェッチしません。
$qb = $this->em->createQueryBuilder();
$qb->select('person')
->addSelect('role')
->addSelect('category')
->from('Person', 'person')
->innerJoin('person.roles', 'role')
->innerJoin('role.categories', 'category');
$result = $qb->getQuery()->getResult();
$ resultには、関連するすべての役割を持つ個人データが含まれますが、エンティティではなくカテゴリの空白の配列が含まれます。もちろん、最終的なクエリは問題側から始まりますが、今のところは反対側にのみ進みたいと思います…</ p>
だから今、私はすべての役割を引き受けて、すべてのカテゴリをフェッチするためにそれらをループする必要があるかどうか疑問に思います。より簡単な教義の方法はありませんか?
ちなみに、それは私が使用するSQLです。
SELECT issue.* FROM person AS p, person_is_member_of_role AS pim, role_has_access_on_category AS rha, issue
WHERE
p.id = pim.person_id AND
pim.role_id = rha.role_id AND
rha.category_id = todo.category AND
p.id = ?;
これですべてが明らかになることを願っています。そうでない場合は、質問を修正します…</ p>