通过 Symfony 中的 Propel 连接表从 3 个表返回记录

发布于 2024-08-24 17:49:51 字数 205 浏览 6 评论 0原文

我有 3 个数据库表:

  • articlearticle_has_tag
  • (其他表的 2 个 FK)
  • 标签

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

我想循环所有文章并依次从每一篇文章中获取标签对象。

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

I have 3 database tables:

  • article
  • article_has_tag (2 FK's to the other tables)
  • tag

I currently show a list of articles with the article's tags shown underneath but the number of queries grows as the list gets longer.

I want to loop over all the articles and get the tag objects from each one in turn.

Can it be done in 1 propel query?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

少女的英雄梦 2024-08-31 17:49:51

我相信您正在使用 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 类中创建一个简单的标签数组(受保护数组 $collTags)以及 addTag() 方法(如果没有)已经存在以促进这一点。

然后,这只会执行一个 SQL 查询,但请认真考虑,如果没有我提到的过滤器,您可能会不必要地水合数百个对象,这对性能会造成重大影响。您可能想研究如何仅基于 doSelectRS() 调用进行水合 - 检查您的 BlahPeer 类以了解其 JOIN 方法的工作原理,然后 此链接了解如何编写自定义 JOIN 方法。

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

I believe you are using symfony 1.0 and thus Propel 1.2... Whilst the methods already described in the comments talk about alternative methods, there is a direct way to at least solve your problem: add this function to your ArticlePeer class:

  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;
  }

where $ahts is short for $article_has_tags. Create a simple array of tags in your Article class (protected array $collTags) along with the addTag() method, if they don't already exist to facilitate this.

This then only executes one SQL query, but consider seriously that without the filter I mention you are potentially hydrating hundreds of objects unnecessarily, and that is a significant performance hit. You may want to research how to hydrate based only on a doSelectRS() call - inspect your BlahPeer classes for how their JOIN methods work, and then this link for how to write custom JOIN methods.

Either way, the method builds a unique array of articles with the ArticleId as the key - if you need a different sort order, you can either sort this array again or use a different array key to organise the collection as you build it.

落花浅忆 2024-08-31 17:49:51

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

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

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

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

Unless I'm misunderstanding your question, don't loop over anything as you'll generate bloat of a different kind.

Do a single query where "article" is joined to "article_has_tag" is joined to "tag". The single query should return the specified articles and tag names for the tags they have.

I use Doctrine myself so can't help you with the exact query but Googling brings up stuff like this: http://www.tech-recipes.com/rx/2924/symfony_propel_how_to_left_join/.

Also, the symfony definitive guide (which was written for Propel) should be able to help you.

遮云壑 2024-08-31 17:49:51

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

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

I assume you are using Propel 1.3 or 1.4, and not yet Propel 1.5 (which is still in beta), as the latter has a very natural support for these multiple joins (inspired, in part, by the Doctrine syntax).

If you defined your foreign keys in the database schema, you should have a static doSelectJoinByAll method in the ArticleHasTagPeer class. If you use this method, the related Article and Tag objects will be hydrated with the same query. You can still pass in a Criteria object that modifies the Article and Tag selection criteria. I know this is a bit strange, since you probably want to start from the Article objects, and this was one of the driving factors for the change in Propel 1.5. In Symfony you can also use the DbFinderPlugin, this will already give you this capability in Propel 1.3 (it needs a small patch for Propel 1.4). In fact, Propel 1.5 is mostly written by François Zaniotto, the author of the DbFinderPlugin.

厌倦 2024-08-31 17:49:51

简短的回答是

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

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

Short answer is no.

But with some efforts you still can do that. Here's list of options:

  1. Use dbFinderPlugin plugin
  2. Write your own peer method (say, doSelectPostWithUsersAndComments).
  3. Migrate to Propel 1.5
  4. Migrate to Doctrine
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文