Symfony 2.2,Doctrine 2:复杂的关系实体检索

See*_*eer 3 php entity symfony doctrine-orm

背景

我正在投资组合网站,网站相当简单,大部分工作都在画廊.我有一组数据库表所有链接起来以不同的方式检索和过滤画廊,从顶部,它如下:

GalleryCategory- > Gallery- >GalleryImage


问题

我面临的问题只出现在图库类别页面上,我正在查看给定类别中的所有图库,然后,图库中的图库图像返回.

我的控制器目前看起来像这样:

public function galleryCategoryAction($categoryId)
{
    $em = $this->getDoctrine()->getManager();

    $category  = $em->getRepository('SeerUKDWrightGalleryBundle:GalleryCategory')->findById($categoryId);
    $galleries = $category->getGalleries();

    $galleryImages = [ ];
    foreach ($galleries as $i => $gallery)
    {
        $galleryImages[$gallery->getId()] = $em->getRepository('SeerUKDWrightGalleryBundle:GalleryImage')
            ->findOneByGalleryId($gallery->getId());
    }

    return $this->render('SeerUKDWrightGalleryBundle:Gallery:category.html.twig', array(
        'category'      => $category,
        'galleries'     => $galleries,
        'galleryImages' => $galleryImages
    ));
}
Run Code Online (Sandbox Code Playgroud)

现在,尽管这确实有效,但我确实想要它,我觉得它只是......错了!获得一个类别的画廊是美观和干净的:

$category  = $em->getRepository('SeerUKDWrightGalleryBundle:GalleryCategory')->findById($categoryId);
$galleries = $category->getGalleries();
Run Code Online (Sandbox Code Playgroud)

但是,我看到获取每个图库的第一个图像的唯一方法是循环它们并检索每个实体.就像我说的,这似乎是错的.

唯一的另一个改进我的建议就是使用库实体中的实体管理器来获取实体中的图像,这当然会破坏Doctrine用于的目的.


结论

总之,我该如何做得更好?必须有一个地方可以做得更好,我只是Symfony的新手.查看文档没有帮助...


额外细节

我忘了提及,仍然能够使用实体的能力是必要的,我在稍后使用的实体上有一些方法.例如,在GalleryImage实体中,我有方法来获取图像的系统路径和Web路径.我仍然需要能够使用它们.

Tho*_*ire 6

你可以做很多事情; 我将列出一个子弹点列表,以便您可以发现它们.

延迟加载会产生额外的查询; 如果您知道要抽取一组关联实体,则可能需要加入这些实体.

以下代码生成两个查询

$category  = $em->getRepository('SeerUKDWrightGalleryBundle:GalleryCategory')->findById($categoryId);
$galleries = $category->getGalleries();
Run Code Online (Sandbox Code Playgroud)

如果您按照文档进行操作,则应执行以下操作(最好在实体的存储库类中)

$em = $this->getDoctrine()->getManager();

$query = $em->createQuery(
    'SELECT gc, g
     FROM SeerUKDWrightGalleryBundle:GalleryCategory gc
     LEFT JOIN gc.galleries g
     WHERE gc.id = :categoryId'
)->setParameter('categoryId', $categoryId);

$category = $query->getResult();
Run Code Online (Sandbox Code Playgroud)

这只是一个查询.

如果你有很多画廊,让我们说100,000,你的服务器将很快耗尽内存,所以你可能想要使用额外的延迟加载选项分页或使用延迟加载.

如果您想要更多地抽象代码,可以在存储库和控制器之间添加服务.

  • 存储库将从数据库中获取数据
  • 服务将调用存储库,获取数据并对其进行操作(如Helper类).
  • 控制器将调用服务并将数据注入模板层(以及其他内容).

如果要获取每个库的第一个图像,可以SELECT使用IN语句和GROUP BY语句创建查询.这样,您可以对所有图库进行一次查询,而不是"x"查询(如果有100,000个图库,则查询100,000个查询).

  • 哦,不要误会,我上面提到的是DQL而不是SQL,Doctrine将解释DQL,将其转换为SQL,将获取数据并默认将数据水合成实体.水合物是用于定义原始数据到实体的转换的术语. (2认同)