duanqianmou4661 2013-03-22 20:16
浏览 47
已采纳

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

Background

I'm working on a portfolio website, the website is fairly simple, the bulk of the work is on the gallery. I have a a set of database tables all linked up to retrieve and filter galleries in different ways, from the top, it is as follows:

GalleryCategory -> Gallery -> GalleryImage


The Problem

The problem I'm facing is only on gallery category pages, where I'm looking at all of the galleries in a given category, and then, the gallery images within the galleries returned.

My controller currently looks like this:

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
    ));
}

Now, as much as this does work, exactly how I want it to, I feel like it's just... wrong! Getting the galleries in a category is nice and clean:

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

But then the only way I see to get the first image of each gallery is to loop over them and retrieve each entity. Like I said, this just seems wrong.

The only other suggestion to improve this that I've had is to use the entity manager in the gallery entity to get images within the entity, this of course would defeat the very purpose that Doctrine is meant to be used for.


Conclusion

In conclusion, how do I do this better? There must be a place to do this better and I'm just new to Symfony. Looking over the documentation hasn't helped...


Additional Details

I forgot to mention, the ability to still be able to use the entities is a necessity, I have some methods on the entities that are used later on. For example, in the GalleryImage entity I have methods to get the system path and web path of the image. I'll still need to be able to use those.

  • 写回答

1条回答 默认 最新

  • doukuiqian9911 2013-03-22 20:49
    关注

    There is a bunch of things you can do; I'll just make a list of bullet points so you can discover them.

    The lazy-loading will generate extra queries; if you know you are going to pull a collection of associated entities you probably need to join these entities.

    The following code generates two queries

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

    If you follow the documentation you should do the following (preferably in the entity's repository class)

    $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();
    

    That's only one query.

    If you have a lot of galleries, let's say 100,000, your server will quickly run out of memory so you might want to paginate or use lazy-loading with the extra lazy loading option.

    If you want to abstract your code even more you can add services between your repositories and your controllers.

    • Repositories would get the data from database
    • Services would call the repositories, get the data and manipulate it (like a Helper class).
    • Controllers would call the services and inject data into the templating layer (among other things).

    If you want to get the first image of each gallery, you can create a SELECT query with a IN statement and a GROUP BY statement. That way you do one query of all galleries rather than 'x' queries (100,000 queries if there are 100,000 galleries).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 求解vmware的网络模式问题 别拿AI回答
  • ¥24 EFS加密后,在同一台电脑解密出错,证书界面找不到对应指纹的证书,未备份证书,求在原电脑解密的方法,可行即采纳
  • ¥15 springboot 3.0 实现Security 6.x版本集成
  • ¥15 PHP-8.1 镜像无法用dockerfile里的CMD命令启动 只能进入容器启动,如何解决?(操作系统-ubuntu)
  • ¥30 请帮我解决一下下面六个代码
  • ¥15 关于资源监视工具的e-care有知道的嘛
  • ¥35 MIMO天线稀疏阵列排布问题
  • ¥60 用visual studio编写程序,利用间接平差求解水准网
  • ¥15 Llama如何调用shell或者Python
  • ¥20 谁能帮我挨个解读这个php语言编的代码什么意思?