通过 Symfony 中的 Propel 连接表从 3 个表返回记录
我有 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我相信您正在使用 symfony 1.0,因此使用 Propel 1.2...虽然评论中已经描述的方法讨论了替代方法,但有一种直接的方法至少可以解决您的问题:将此函数添加到您的
ArticlePeer 类:
其中
$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:where
$ahts
is short for$article_has_tags
. Create a simple array of tags in yourArticle
class (protected array $collTags
) along with theaddTag()
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 customJOIN
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.
除非我误解了你的问题,否则不要循环任何内容,因为你会产生另一种类型的膨胀。
执行一个查询,其中“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.
我假设您正在使用 Propel 1.3 或 1.4,而不是 Propel 1.5(仍处于测试阶段),因为后者具有 对这些多重连接的非常自然的支持(部分受到 Doctrine 语法的启发)。
如果您在数据库架构中定义了外键,则
ArticleHasTagPeer
类中应该有一个静态doSelectJoinByAll
方法。如果您使用此方法,相关的Article
和Tag
对象将使用相同的查询进行水合。您仍然可以传入一个Criteria
对象来修改Article
和Tag
选择条件。我知道这有点奇怪,因为您可能想从 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 theArticleHasTagPeer
class. If you use this method, the relatedArticle
andTag
objects will be hydrated with the same query. You can still pass in aCriteria
object that modifies theArticle
andTag
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.简短的回答是否。
但通过一些努力,你仍然可以做到这一点。以下是选项列表:
doSelectPostWithUsersAndComments
)。Short answer is no.
But with some efforts you still can do that. Here's list of options:
doSelectPostWithUsersAndComments
).