仅选择页面上链接的相关新闻项目(多个一两个关系)

lam*_*ade 4 php mysql symfony doctrine-orm

我有一个page由多个containers 组成的实体.在那些容器中,用户可以链接news list.那些news list再次包含news items.

现在,我想搜索news items,但我需要pagenews list是在挂为好.

我试过这个:

$query = $this->getEntityManager()->createQuery('
    SELECT p, c, n, i
    FROM VendorNameBundle:Page p
    LEFT JOIN p.container c
    LEFT JOIN c.news n
    LEFT JOIN n.items i
    WHERE i.title LIKE :title
    GROUP BY i.id
');
Run Code Online (Sandbox Code Playgroud)

这基本上起作用,因为它给了我正确的页面.但要找到正确的,news item我必须贯穿所有containers和他们的news lists.当然,当我检索所有项目时,我不仅仅是搜索的重要项目.

我怎样才能以优雅的方式解决这个问题?

总结:我需要news items和他们相应的page实体.我怎样才能以一种整洁优雅的方式解决这个问题?

注意:如果a news list在多个页面上列出page,则结果中的一个就足够了,并不重要.

编辑

以下是评论中要求的关系:

/**
 * @ORM\OneToMany(targetEntity="Container", mappedBy="page", cascade={"remove"})
 * @ORM\OrderBy({"position" = "asc"})
 */
protected $containers;
Run Code Online (Sandbox Code Playgroud)

容器

/**
 * @ORM\ManyToOne(targetEntity="Page", inversedBy="containers")
 * @ORM\JoinColumn(name="Page_id", referencedColumnName="id")
 */
private $page;

/**
 * @ORM\ManyToOne(targetEntity="News", inversedBy="containers")
 * @ORM\JoinColumn(name="news_id", referencedColumnName="id", onDelete="SET NULL")
 */
protected $news;
Run Code Online (Sandbox Code Playgroud)

新闻

/**
 * @ORM\OneToMany(targetEntity="Container", mappedBy="news")
 */
protected $containers;
Run Code Online (Sandbox Code Playgroud)

Jas*_*wer 5

查询

因为您正在搜索新闻项目,我建议您使用这些新闻项目直到页面(而不是相反):

SELECT i, n, c, p
FROM VendorNameBundle:Item i
JOIN i.news n
JOIN n.container c
JOIN c.page p
WHERE i.title LIKE :title
Run Code Online (Sandbox Code Playgroud)

此查询确实假设每个新闻项都在新闻列表中,每个新闻列表都在一个容器内,每个容器都在一个页面内.如果不是这样,请使用a LEFT JOIN而不是a JOIN,否则你会错过一些新闻.

分组

此查询将为您提供所需的数据,但可能没有按您希望的方式格式化.如果要对每页或新闻列表(等)进行分组,则需要手动(在代码中)执行此操作.

但是,您可以让查询执行某些排序,因此分组(在代码中)变得更容易.以下示例将首先按页面标题排序结果,然后是新闻列表的标题:

SELECT i, n, c, p
FROM VendorNameBundle:Item i
JOIN i.news n
JOIN n.container c
JOIN c.page p
WHERE i.title LIKE :title
ORDER BY p.title ASC, n.title ASC
Run Code Online (Sandbox Code Playgroud)

现在分组可以像这样完成:

$currentPage     = null;
$currentNewsList = null;

foreach ($newsItems as $newsItem) {
    $newsList = $newsItem->getNews();
    $page     = $newsList->getContainer()->getPage();

    if ($page !== $currentPage) {
        $currentPage = $page;
        echo '- ' . $page->getTitle() . "\n";
    }

    if ($newsList !== $currentNewsList) {
        $currentNewsList = $newsList;
        echo '    - ' . $newsList->getTitle() . "\n";
    }

    echo '        - ' . $newsItem->getTitle() . "\n";
}
Run Code Online (Sandbox Code Playgroud)

哪个会打印这样的东西:

- Page A
    - News list A
        - Found news item
    - News list C
        - Another found news item
- Page B
    - News list B
        - Yet another found news item
Run Code Online (Sandbox Code Playgroud)