Symfony2,Doctrine,延迟加载和代理类问题
Posted
技术标签:
【中文标题】Symfony2,Doctrine,延迟加载和代理类问题【英文标题】:Symfony2, Doctrine, Lazy Loading and Proxy Class issue 【发布时间】:2014-08-20 04:04:35 【问题描述】:首先,我要感谢 *** 社区在过去几年中为我提供的所有帮助!我通常会找到解决方案,但这一次,经过数小时的研究和测试,我无法得到任何解决方案。所以这是我的问题:
在我的页面顶部,我有一个从带有类别的数据库生成的菜单。这是我的代码的一部分:
类别控制器:
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);
这是我的问题:此代码在任何页面上都可以正常工作,但对元素有自定义请求的页面除外。
索引控制器
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 函数结束时:它也在索引页面上工作!
如果我将 getNews 函数替换为 getArtist(根据菜单),设置为“无翻译”的 Artist 菜单类别也会出现同样的问题
我认为这是 Doctrine 的延迟加载问题,但也许有一些我不明白的地方。
如果您有任何想法,我正在等待您的帮助!提前致谢!
【问题讨论】:
请问,如果您对 SO 这么感兴趣,为什么要为这个问题创建一个新帐户? 第一次参加,在这里提问。所以这是我在 *** 上的第一个帐户。 【参考方案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对象)时,返回的Category(只针对有Articles的Category)不是Heidan\CoreBundle\的对象Entity\Category 但 Proxies__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
希望这对其他人有所帮助。
【讨论】:
以上是关于Symfony2,Doctrine,延迟加载和代理类问题的主要内容,如果未能解决你的问题,请参考以下文章
使用 Doctrine 和 Symfony2 查询多对多关系
Symfony Doctrine ORM ManyToMany - 带有标签的博客 - 我没有从博客中获取所有标签,没有延迟加载