DQL 的 Doctrine 2 反向成员
Doctrine 2 reverse MEMBER OF DQL
我有 Profile class 与 ManyToMany 关系 "links" 和 Link class。
我需要构建 DQL 查询以获取某些配置文件 的所有 link,而没有 反向关系(link->配置文件)。
第一个想法是简单使用 "MEMBER OF" 但看起来没有直接关系是不可能的。
MEMEBER OF 正在构建子查询 sql。也许有办法做类似的事情?
我不能只使用
SELECT l FROM Profile p LEFT JOIN p.links l WHERE p.user = :user
但我能做到:
SELECT e FROM Link WHERE e.id IN (SELECT l FROM Profile p LEFT JOIN p.links l WHERE p.user = :user)
所以我生成了这个 SQL:
SELECT ... FROM Link t0_
WHERE t0_.id IN (
SELECT t1_.id FROM Profile a2_
LEFT JOIN profile_link p3_ ON a2_.user_id = p3_.profile_user_id
LEFT JOIN Link t1_ ON t1_.id = p3_.link_id
WHERE a2_.user_id = ?
)
有什么方法可以在不加入配置文件的情况下直接为 table profile_link 构建子查询?
类似于:
SELECT ... FROM Link t0_
WHERE t0_.id IN (
SELECT l.link_id FROM profile_link l
WHERE l.profile_id = :user
)
P.S。无需使用配置文件 table.
profile_link.profile_id = profile.user_id = user.id = :user
我需要一个 DQL 查询构建器来构建具有 filter/sorter/grouper 支持的更复杂的查询。我不能在这里使用本机查询或修改实体 class。也许某种自定义 DQL 函数可以解决它。
我相信你想多了。
您可以通过定义的链接关系获取个人资料实体的链接。
我假设您的个人资料 class 看起来像:
use Doctrine\ORM\Mapping as ORM;
class Profile
{
/**
* @var integer
*
* @ORM\Column(name="user_id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="Link")
* @ORM\JoinTable(name="profile_link",
* joinColumns={@ORM\JoinColumn(name="profile_user_id", referencedColumnName="user_id")},
* inverseJoinColumns={@ORM\JoinColumn(name="link_id", referencedColumnName="id")}
* )
**/
protected $links;
public function getLinks()
{
return $this->links;
}
您可以通过以下方式实现您想要的:
- 正在加载配置文件实体
- 获得链接关系
- 遍历返回的集合,这取决于 relation fetch mode(急切的、懒惰的或极度懒惰的),如果尚未从上述步骤中获取实体,则将导致获取实体。
在您的控制器中,只需执行以下操作:
$profile = $em->getRepository('AppBundle\Entity\Profile')->find(1);
$links = $profile->getLinks();
foreach($links as $link) {
echo $link->getId();
}
这样将执行 2 个查询:
1) 获取配置文件行,例如:
SELECT t0.user_id AS user_id_1 FROM profile t0 WHERE t0.user_id = ?
2) 获取相关链接,例如:
SELECT t0.id AS id_1 FROM link t0 INNER JOIN profile_link ON t0.id = profile_link.link_id WHERE profile_link.profile_user_id = ?
在最后一个查询中,只加入了映射 table,没有加入配置文件 table。返回的行不包含配置文件数据。
我放弃了。
ManyToMany realtion 是一对简单的 OneToMany realtions,所以我创建了 class 来表示它。
class ProfileLink{
/**
* @ORM\Id
* @ORM\OneToMany(targetEntity="Profile")
*/
protected $profile;
/**
* @ORM\Id
* @ORM\OneToMany(targetEntity="Link")
*/
protected $link;
}
现在我可以在 Link class
上使用没有反向部分的 DQL
SELECT p FROM ProfileLink LEFT JOIN p.link WHERE p.profile = :user_id;
我有 Profile class 与 ManyToMany 关系 "links" 和 Link class。 我需要构建 DQL 查询以获取某些配置文件 的所有 link,而没有 反向关系(link->配置文件)。
第一个想法是简单使用 "MEMBER OF" 但看起来没有直接关系是不可能的。
MEMEBER OF 正在构建子查询 sql。也许有办法做类似的事情?
我不能只使用
SELECT l FROM Profile p LEFT JOIN p.links l WHERE p.user = :user
但我能做到:
SELECT e FROM Link WHERE e.id IN (SELECT l FROM Profile p LEFT JOIN p.links l WHERE p.user = :user)
所以我生成了这个 SQL:
SELECT ... FROM Link t0_
WHERE t0_.id IN (
SELECT t1_.id FROM Profile a2_
LEFT JOIN profile_link p3_ ON a2_.user_id = p3_.profile_user_id
LEFT JOIN Link t1_ ON t1_.id = p3_.link_id
WHERE a2_.user_id = ?
)
有什么方法可以在不加入配置文件的情况下直接为 table profile_link 构建子查询?
类似于:
SELECT ... FROM Link t0_
WHERE t0_.id IN (
SELECT l.link_id FROM profile_link l
WHERE l.profile_id = :user
)
P.S。无需使用配置文件 table.
profile_link.profile_id = profile.user_id = user.id = :user
我需要一个 DQL 查询构建器来构建具有 filter/sorter/grouper 支持的更复杂的查询。我不能在这里使用本机查询或修改实体 class。也许某种自定义 DQL 函数可以解决它。
我相信你想多了。
您可以通过定义的链接关系获取个人资料实体的链接。
我假设您的个人资料 class 看起来像:
use Doctrine\ORM\Mapping as ORM;
class Profile
{
/**
* @var integer
*
* @ORM\Column(name="user_id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="Link")
* @ORM\JoinTable(name="profile_link",
* joinColumns={@ORM\JoinColumn(name="profile_user_id", referencedColumnName="user_id")},
* inverseJoinColumns={@ORM\JoinColumn(name="link_id", referencedColumnName="id")}
* )
**/
protected $links;
public function getLinks()
{
return $this->links;
}
您可以通过以下方式实现您想要的:
- 正在加载配置文件实体
- 获得链接关系
- 遍历返回的集合,这取决于 relation fetch mode(急切的、懒惰的或极度懒惰的),如果尚未从上述步骤中获取实体,则将导致获取实体。
在您的控制器中,只需执行以下操作:
$profile = $em->getRepository('AppBundle\Entity\Profile')->find(1);
$links = $profile->getLinks();
foreach($links as $link) {
echo $link->getId();
}
这样将执行 2 个查询:
1) 获取配置文件行,例如:
SELECT t0.user_id AS user_id_1 FROM profile t0 WHERE t0.user_id = ?
2) 获取相关链接,例如:
SELECT t0.id AS id_1 FROM link t0 INNER JOIN profile_link ON t0.id = profile_link.link_id WHERE profile_link.profile_user_id = ?
在最后一个查询中,只加入了映射 table,没有加入配置文件 table。返回的行不包含配置文件数据。
我放弃了。
ManyToMany realtion 是一对简单的 OneToMany realtions,所以我创建了 class 来表示它。
class ProfileLink{
/**
* @ORM\Id
* @ORM\OneToMany(targetEntity="Profile")
*/
protected $profile;
/**
* @ORM\Id
* @ORM\OneToMany(targetEntity="Link")
*/
protected $link;
}
现在我可以在 Link class
上使用没有反向部分的 DQLSELECT p FROM ProfileLink LEFT JOIN p.link WHERE p.profile = :user_id;