我有 3 个数据库表:
- 文章
- article_has_tag(其他表的 2 个 FK)
- 标签
我目前显示了一个文章列表,文章的标签显示在下面,但是查询的数量随着列表的变长而增加。
我想遍历所有文章并依次从每个文章中获取标签对象。
可以在 1 个推进查询中完成吗?
我相信您使用的是 symfony 1.0 和 Propel 1.2...虽然评论中已经描述的方法讨论了替代方法,但至少有一种直接的方法可以解决您的问题:将此函数添加到您的ArticlePeer类中:
public static function getTaggedArticles()
{
$c = new Criteria();
//some filters here, e.g. LIMIT or Criteria::IN array
$ahts = ArticleHasTagPeer::doSelectJoinAll($c);
$articles = array();
foreach($ahts as $aht)
{
if(!isset($articles[$aht->getArticleId()]))
{
$articles[$aht->getArticleId()] = $aht->getArticle();
}
$articles[$aht->getArticleId()]->addTag($aht->getTag());
}
return $articles;
}
哪里$ahts是$article_has_tags. Article在您的类 ( protected array $collTags)中创建一个简单的标签数组以及addTag()方法,如果它们不存在的话。
然后这只执行一个 SQL 查询,但请认真考虑,如果没有我提到的过滤器,您可能会不必要地水合数百个对象,这是对性能的重大影响。您可能想研究如何仅基于 doSelectRS() 调用进行水合 - 检查您的 BlahPeer 类以了解它们的JOIN方法如何工作,然后通过此链接了解如何编写自定义JOIN方法。
无论哪种方式,该方法都会构建一个以 ArticleId 作为键的唯一文章数组 - 如果您需要不同的排序顺序,您可以再次对该数组进行排序,或者在构建集合时使用不同的数组键来组织集合。
除非我误解了你的问题,否则不要循环任何东西,因为你会产生另一种膨胀。
执行单个查询,其中“article”连接到“article_has_tag”连接到“tag”。单个查询应返回指定的文章和它们所拥有标签的标签名称。
我自己使用 Doctrine,因此无法帮助您进行确切的查询,但谷歌搜索会显示如下内容:http ://www.tech-recipes.com/rx/2924/symfony_propel_how_to_left_join/ 。
此外,symfony 权威指南(为 Propel 编写的)应该能够为您提供帮助。
我假设您使用的是 Propel 1.3 或 1.4,而不是 Propel 1.5(仍处于测试阶段),因为后者非常自然地支持这些多重连接(部分受到 Doctrine 语法的启发)。
如果您在数据库模式中定义了外键,那么您应该doSelectJoinByAll在类中有一个静态方法ArticleHasTagPeer。如果使用此方法,相关对象Article和Tag对象将使用相同的查询进行水合。您仍然可以传入Criteria修改Article和Tag选择条件的对象。我知道这有点奇怪,因为您可能想从 Article 对象开始,这是 Propel 1.5 更改的驱动因素之一。在 Symfony 中,您还可以使用DbFinderPlugin,这已经在 Propel 1.3 中为您提供了此功能(它需要Propel 1.4的一个小补丁)。事实上,Propel 1.5 主要由 DbFinderPlugin 的作者 François Zaniotto 编写。
简短的回答是否定的。
但是通过一些努力,你仍然可以做到这一点。以下是选项列表:
doSelectPostWithUsersAndComments)。