Symfony2,Doctrine,Lazy Loading和Proxy Class问题

时间:2014-08-20 04:04:35

标签: php sql symfony doctrine-orm doctrine

首先,我要感谢stackoverflow社区提供过去几年提供给我的所有帮助!我通常会找到一个解决方案,但这次和经过数小时的研究和测试后,我无法解决问题。所以这是我的问题:

在我的页面顶部,我有一个从带有类别的数据库生成的菜单。这是我的代码的一部分:

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引用此请求,以获取lvl0类别:

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,则它会在Index Page上工作。

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

如果我用getArtist替换我的函数getNews(根据菜单),则艺术家菜单类别会出现同样的问题,这些类别被设置为' No Translation'

我认为这是一个来自Doctrine的懒惰加载问题,但也许有些东西我还没有理解。

如果您有任何想法,我会等待您的帮助!提前谢谢!

1 个答案:

答案 0 :(得分:1)

我在使用调试器后终于找到了解决方案。我的第一个虽然是一半,一半是错的。问题是由于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()方法(返回Article对象)时,返回的类别(仅适用于具有文章的类别)不是 Heidan \ CoreBundle \的对象实体\类别代理_CG __ \ Heidan \ CoreBundle \ Entity \ Category

所以,这设置我的条件if(get_class($ object)=='Heidan \ CoreBundle \ Entity \ Category')为false且类别未翻译

为了获得正确的行为,我不得不将实体管理器注入我的事件并使用函数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);
        }
    }

}

此链接帮助了我Get entity name from class object

希望这有助于其他人。