Symfony2、教条、延迟加载和代理类问题


Symfony2, Doctrine, Lazy Loading and Proxy Class issue

首先我要感谢stackoverflow社区在过去几年里给予我的所有帮助!我通常都能找到解决办法,但这一次,经过长时间的研究和测试,我还是找不到任何解决办法。这是我的问题:

在我的页面的顶部,我有一个菜单,是从一个DB与类别生成的。下面是我的一部分代码:

CategoryController:

public function renderMenuAction() {
    $em = $this->getDoctrine()->getManager();
    $manager = new CategoryManager($em);
    $request = $this->getRequest();
    $categories = $manager->loadMenu();
    foreach($categories as $category) {
        $this->getLocalizedCategoryTranslations($category, $request);
    }
    return $this->render('HeidanCoreBundle:Includes/Category:category_menu.html.twig', array(
        'categories' => $categories,
    ));
}

函数loadMenu从我的经理引用这个请求,以获得lv0类别:

CategoryRepository:

public function findMenuElements() {
    $qb = $this->_em->createQueryBuilder();
    $qb->select('category', 'translation')
       ->from('HeidanCoreBundle:Category', 'category')
       ->leftJoin('category.translations', 'translation')
       ->where('category.lvl = 0')
       ;
    return $query = $qb->getQuery()
            ->getResult();
}

getLocalizedCategoryTranslations调用侦听器,该侦听器设置类别(标题,描述等)的翻译值

public function getLocalizedCategory(TranslatableEvent $event)
{
    $object = $event->getObject();
    $locale = $event->getLocale();
    if($object instanceof TranslatableInterface) {
        if(get_class($object) == 'Heidan'CoreBundle'Entity'Category') {
            $this->localizeObject($object, $locale);
            $this->localizeCategoryChildren($object, $locale);
        }
    }
}

这是我的问题:这段代码在任何页面上都没有任何问题,除了那些对元素有自定义请求的页面。

IndexController

public function indexAction()
{
    $news = $this->getNews();
    $announcements = $this->getAnnouncements();
    return $this->render('HeidanCoreBundle:Public:index.html.twig', array(
        'news' => $news,
        'announcements' => $announcements,
    ));
}
public function getNews() {
    $em = $this->getDoctrine()->getManager();
    $qb = $em->createQueryBuilder();
    $qb->select('article')
       ->from('HeidanCoreBundle:Article', 'article')
       ->orderBy('article.createdAt', 'DESC')
       ->setMaxResults(4);
    $query = $qb->getQuery();
    $results = $query->getResult();
    return $results;
}

这是我的菜单的描述。

管理页面(没有像上面的getNews这样的自定义查询-所有这些对象都是类别):

,

——社会

——业务

——艺术品

,书

——歌曲

——艺术家

——作者

——歌手

索引页(有一个请求文章的getNews查询):

——没有翻译

——没有翻译

——没有翻译

——艺术品

,书

——歌曲

——艺术家

——作者

——歌手

可以看到,对象翻译没有显示在索引页上。我检查了Symfony调试模式,它根本没有被要求。(对于ID为1、13、14的类别,没有选择翻译查询来获取翻译,而对于其他类别,查询已经完成)。

我尝试了几种方法:

如果我删除getNews()并将其替换为null,它将在索引页上工作。

如果我添加$query->setHint(query::HINT_FORCE_PARTIAL_LOAD, true);在我的getNews函数结束时:它也在索引页上工作!

如果我用getArtist(根据菜单)替换我的函数getNews,同样的问题出现在设置为'No Translation'的Artist菜单类别

我认为这是一个从学说的延迟加载问题,但可能有什么我没有理解。

如果你有任何想法,我在等待你的帮助!

我终于在使用调试器后找到了解决方案。我的第一个想法一半对,一半错。问题是由于Doctrine行为,但它来自我的一行代码。

public function getLocalizedCategory(TranslatableEvent $event)
{
    $object = $event->getObject();
    $locale = $event->getLocale();
    if($object instanceof TranslatableInterface) {
        if(get_class($object) == 'Heidan'CoreBundle'Entity'Category') {
            $this->localizeObject($object, $locale);
            $this->localizeCategoryChildren($object, $locale);
        }
    }
}

在这个函数中(我编辑了问题,也让这部分代码出现),我调用get_class方法。

当我使用调试器时,我发现当我调用getNews()方法(返回文章对象)时,返回的类别(仅适用于具有文章的类别)不是Heidan'CoreBundle'Entity'Category而是Proxies__CG__'Heidan'CoreBundle'Entity'Category的对象

因此,这设置了我的条件if(get_class($object) == 'Heidan'CoreBundle'Entity'Category')为false并且Category未被翻译

为了获得正确的行为,我必须将实体管理器注入到事件中,并使用函数getClassMetadata

获取类名

正确getLocalizedCategory函数:

public function getLocalizedCategory(TranslatableEvent $event)
{
    $object = $event->getObject();
    $locale = $event->getLocale();
    $em = $event->getEm();
    if($object instanceof TranslatableInterface) {
        $className = $em->getClassMetadata(get_class($object))->getName();
        if($className == 'Heidan'CoreBundle'Entity'Category') {
            $this->localizeObject($object, $locale);
            $this->localizeCategoryChildren($object, $locale);
        }
    }
}

这个链接帮助我从类对象中获取实体名称