0

我有 3 个数据库表:

  • 文章
  • article_has_tag(其他表的 2 个 FK)
  • 标签

我目前显示了一个文章列表,文章的标签显示在下面,但是查询的数量随着列表的变长而增加。

我想遍历所有文章并依次从每个文章中获取标签对象。

可以在 1 个推进查询中完成吗?

4

4 回答 4

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 作为键的唯一文章数组 - 如果您需要不同的排序顺序,您可以再次对该数组进行排序,或者在构建集合时使用不同的数组键来组织集合。

于 2010-03-15T21:52:39.547 回答
0

除非我误解了你的问题,否则不要循环任何东西,因为你会产生另一种膨胀。

执行单个查询,其中“article”连接到“article_has_tag”连接到“tag”。单个查询应返回指定的文章和它们所拥有标签的标签名称。

我自己使用 Doctrine,因此无法帮助您进行确切的查询,但谷歌搜索会显示如下内容:http ://www.tech-recipes.com/rx/2924/symfony_propel_how_to_left_join/ 。

此外,symfony 权威指南(为 Propel 编写的)应该能够为您提供帮助。

于 2010-03-14T23:43:32.157 回答
0

我假设您使用的是 Propel 1.3 或 1.4,而不是 Propel 1.5(仍处于测试阶段),因为后者非常自然地支持这些多重连接(部分受到 Doctrine 语法的启发)。

如果您在数据库模式中定义了外键,那么您应该doSelectJoinByAll在类中有一个静态方法ArticleHasTagPeer。如果使用此方法,相关对象ArticleTag对象将使用相同的查询进行水合。您仍然可以传入Criteria修改ArticleTag选择条件的对象。我知道这有点奇怪,因为您可能想从 Article 对象开始,这是 Propel 1.5 更改的驱动因素之一。在 Symfony 中,您还可以使用DbFinderPlugin,这已经在 Propel 1.3 中为您提供了此功能(它需要Propel 1.4的一个小补丁)。事实上,Propel 1.5 主要由 DbFinderPlugin 的作者 François Zaniotto 编写。

于 2010-03-15T08:39:42.477 回答
-2

简短的回答是否定的。

但是通过一些努力,你仍然可以做到这一点。以下是选项列表:

  1. 使用dbFinderPlugin插件
  2. 编写您自己的对等方法(例如doSelectPostWithUsersAndComments)。
  3. 迁移到 Propel 1.5
  4. 迁移到教义
于 2010-03-15T13:06:45.563 回答