【问题标题】:Returning records from 3 tables via a Join Table with Propel in Symfony在 Symfony 中通过带有 Propel 的连接表从 3 个表中返回记录
【发布时间】:2010-03-14 23:24:42
【问题描述】:

我有 3 个数据库表:

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

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

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

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

【问题讨论】:

    标签: php sql symfony1 propel


    【解决方案1】:

    我相信您使用的是 symfony 1.0 和 Propel 1.2...虽然 cmets 中已经描述的方法讨论了替代方法,但至少有一种直接的方法可以解决您的问题:将此功能添加到您的 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 方法的工作原理,然后检查 this link 以了解如何编写自定义 JOIN 方法。

    无论哪种方式,该方法都会以 ArticleId 作为键构建一个唯一的文章数组 - 如果您需要不同的排序顺序,您可以再次对该数组进行排序,或者在构建集合时使用不同的数组键来组织集合.

    【讨论】:

    • 这很棒。谢谢!我总是使用 setLimit() 所以开销不应该太大。
    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案3】:

      我假设您使用的是 Propel 1.3 或 1.4,但尚未使用 Propel 1.5(仍处于测试阶段),因为后者具有用于这些多个连接的 a very natural support(部分受到 Doctrine 语法的启发)。

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

      【讨论】:

        【解决方案4】:

        简短的回答是

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

        1. 使用dbFinderPlugin插件
        2. 编写您自己的对等方法(例如,doSelectPostWithUsersAndComments)。
        3. 迁移到 Propel 1.5
        4. 迁移到教义

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-03
          • 1970-01-01
          • 2013-12-22
          • 1970-01-01
          • 2012-01-03
          • 1970-01-01
          相关资源
          最近更新 更多