我有 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
)。