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).

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

报告相同问题?

悬赏问题

  • ¥60 pb数据库修改或者求完整pb库存系统,需为pb自带数据库
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错
  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上
  • ¥20 关于#anlogic#sdram#的问题,如何解决?(关键词-performance)
  • ¥15 相敏解调 matlab
  • ¥15 求lingo代码和思路