Symfony 5 和 Doctrine,找不到使用 3 个相关实体获取结果的方法

Posted

技术标签:

【中文标题】Symfony 5 和 Doctrine,找不到使用 3 个相关实体获取结果的方法【英文标题】:Symfony 5 and Doctrine, can't find a way to fetch results with 3 related entities 【发布时间】:2021-03-04 06:49:08 【问题描述】:

编辑:这个问题已经更新,我现在很好,感谢与@Jakumi 聊天。

我有多个网站在同一个 Symfony 5 安装上运行。 该网站根据视频类别显示视频,但它们共享相同的视频数据库。 我有一个名为“视频”、“网站”的实体,最后一个名为“类别”:

实体/视频.php

/**
 * @ORM\ManyToMany(targetEntity=Category::class, inversedBy="videos")
 * @ORM\OrderBy("priority" = "DESC")
*/
private $category;

实体/类别.php

/**
 * @ORM\ManyToMany(targetEntity=Video::class, mappedBy="category")
*/
private $videos;

实体/Website.php

/**
 * @ORM\ManyToMany(targetEntity=Category::class, inversedBy="websites")
*/
private $categories;

例如,我有 4 个视频及其类别。

video
id  title
1  | "Lol Pro PLayer"
2  | "Lol Casual Player"
3  | "Counter Strike Casual Player"
4  | "Counter Strike Pro Player"


website
id | title
1  | "LOL PROS"
2  | "CS Gamers"
3  | "CS Pro Gamers"


category
id | title
1  | "Pro"
2  | "League of Legend"
3  | "Counter Strike"


video_category
video_id | category_id
1        | 1
1        | 2
2        | 2
3        | 3
4        | 1
4        | 3


website_category
website_id | category_id
1          | 1
1          | 2
2          | 3
3          | 1
3          | 2

目前,我能够获得这样的视频(肮脏的方式),我第一次硬编码了网站类别 ID。

网站 1 应该只显示属于“职业”和“英雄联盟”两个类别的视频(每个网站可以有 3 或 4 个类别),因此在他的示例中,只有名为“ Lol Pro Player" (id : 1)

App\Repository\VideoRepository.php

public function findWebsiteVideos($website)

    $em = $this->getEntityManager();
    return $query = $em->createQuery(
        'SELECT v
        FROM App\Entity\Video v
        WHERE v.id IN(
            SELECT DISTINCT v_1.id
            FROM App\Entity\Video v_1
            JOIN v_1.category vc_1
            WHERE vc_1.id = 408
        )
        AND v.id IN(
            SELECT DISTINCT v_2.id
            FROM App\Entity\Video v_2
            JOIN v_2.category vc_2
            WHERE vc_2.id = 454
        )
        AND v.id IN(
            SELECT DISTINCT v_3.id
            FROM App\Entity\Video v_3
            JOIN v_3.category vc_3
            WHERE vc_3.id = 504
        )
        ORDER BY v.id ASC'
    );

我正在尝试找到正确的 DQL 以避免脏活,我需要提一下,我不能在当前的分页系统中使用“HAVING”。

【问题讨论】:

你为什么要寻找在 Doctrine 中使用的 SQL 查询?为什么不使用存储库或 DQL? 感谢您的回答。我已经更新了我的问题以使其更清楚。现在,我不明白如何编写有关此查询的 DQL。在能够编写这个之后,我将不得不努力编写一个我不需要硬编码网站类别 ID 的那个。此代码目前有效,但我想编写“良好实践”代码。 不知道你所说的“肮脏的工作”,当它是避免它的目标时很难回答;o) 我的意思是我目前正在对网站类别进行循环以创建 SQL 查询,我认为它可以用 DQL 很好地完成。 :// 我希望您知道,您的查询已经 DQL,您可能指的是查询生成器。我很确定您可能会在子查询中使用HAVING,这可能会有很大帮助。 ;o) 【参考方案1】:

视频存储库中会执行类似的操作:

$qb->createQueryBuilder(‘v’);
 $qb->join(‘v.category’, ‘c’)
   ->join(‘c.websites, ‘w’)
   ->where($qb->expr()->eq(‘w.id’, ‘:website’))
   ->setParameter(‘website’, $your_website_id)
   ->getQuery()->getArrayResult();

根据编辑,您将需要进行两次查询/这样会更快/

首先获取网站类别和基于这些类别的视频查询

【讨论】:

感谢您的帮助,是的,我做了一个这样的(不像这个简单,我觉得很笨),这接近工作,但它提供的视频没有“所有必需的类别”。它在网站“LOL Pros”(id:1)上获取视频“Lol Casual Player”(id:2),其中网站类别为“Pro”和“League of Legend”,我应该只有视频 1。这是我的问题开始。 实际上根据您的架构 1- 查询应该返回 3 个视频 ID 1,2 和 4,因为网站 1 分配给包含这 3 个视频的类别 1 和 2。视频 2 显示为结果,因为它属于类别 2,网站 1 被分配到... 是的,因为它在网站类别上执行类似于 OR 的操作,但我想要 AND,这是我在 DQL 中找不到的。来自网站 1(“Pro”、“League of Legends”)的视频应该只包含“Pro”和“League Of Legends”猫中的视频,而不仅仅是猫“Pro”或猫“League of Legends”中的视频。在纯 SQL 中是可以的,但在 DQL 中,它就像网站类别中的“OR”。

以上是关于Symfony 5 和 Doctrine,找不到使用 3 个相关实体获取结果的方法的主要内容,如果未能解决你的问题,请参考以下文章

Symfony2:学说“找不到驱动程序”

Symfony 和 Doctrine 使迁移无效

使用 Doctrine orm symfony 创建新数据库时出错

测试 Symfony 包:找不到教义.orm.entity

Symfony2 - 在链配置的命名空间中找不到类“X”

Symfony2 / Doctrine 使 $statement->execute() 不“缓冲”所有值