Chinaunix

标题: Cakephp中用join进行多对多关联查询 [打印本页]

作者: sbguh    时间: 2009-11-05 14:09
标题: Cakephp中用join进行多对多关联查询
我今天要说的是对hasAndBelongsToMany关联模式进行筛选查询,如一篇文章有很多个tag,而一个tag同时也会对应很多篇文章,这就属于典型的多对多hasAndBelongsToMany关联模式,那么如果我想查询某一个tag所对应的所有的文章呢?这样的查询在cakephp应该怎么去写呢?

情景:

一个articles表对应(Article) --字段假设是(id,title,content)
一个tags表对应(Tag) - 字段假设是(id,name)
这两个表属于多对多关系
Article中定义
  1.         var $hasAndBelongsToMany = array(
  2.                 'Tag' => array(
  3.                         'className' => 'Tag',
  4.                         'joinTable' => 'tags_articles',
  5.                         'foreignKey' => 'article_id',
  6.                         'associationForeignKey' => 'tag_id',
  7.                 )
  8.         );
复制代码
Tag模型中定义
  1. var $hasAndBelongsToMany = array(
  2.                 'Article' => array(
  3.                         'className' => 'Article',
  4.                         'joinTable' => 'tags_articles',
  5.                         'foreignKey' => 'tag_id',
  6.                         'associationForeignKey' => 'article_id',
  7.                 )
  8.         );
复制代码
由此可见两个model表都是通过第三个表tags_articles进行关联
tags_articles字段假设是(tag_id , article_id)

现在假设我有这样的一个需求:我要得到tag中name='test'所有的文章(article)

如果我们这样写$this->Article->find('all',array('conditions'=>array('Tag.name'=>'test'))),那么系统执行的时候会出现一个错误'Unknown column 'Tag.name' in 'where clause'',因为这种直接写条件的查询方式目前据我所知还只适合hasOne和belongsTo的关联模式,对hasMany和hasAndBelongsToMany关联模式还是不支持的

我不知道别人都是怎么做这个查询的,不过我见过有人是这样做的,先根据name在tags表里面查询到这个tag的id,然后通过这个ID去tags_articles表中查询到所有关联此tag_id的article_id,然后再根据取得的article_id在Article表中进行查询,最后才查询到所要的值。

但是我一直觉得这样太过于麻烦了,要做好几次查询,最好我查资料想到了一个似乎比较好的方法,大家看我最后写的查询语句
  1. $this->Article->find('all',array(
  2.                         'conditions' => array('Tag.name'=>'test'),
  3.                         'joins'=>array(array(
  4.                                 'table'=>'tags_articles',
  5.                                 'alias'=>'TagsArticle',
  6.                                 'type'=>'left',
  7.                         'conditions'=> array('Article.id = TagsArticle.article_id'),
  8.                                 ),
  9.                         array(
  10.                                 'table'=>'tags',
  11.                                 'alias'=>'Tag',
  12.                                 'type'=>'left',
  13.                         'conditions'=> array('Tag.id = TagsArticle.tag_id'),
  14.                                 )
  15.                         )
  16.                         
  17.                 ))
复制代码
大家可以试试我这种方法,当然这并不一定是个好方法,呵呵,大家如果有更好的方法希望共享共享哦, 最后大家可以访问我的网站一起交流学习http://www.shopokey.com
作者: bs    时间: 2009-11-05 19:17
ORM的难处在于对复杂sql的处理是否高效、优化,这个很重要
作者: shopokey    时间: 2009-11-05 20:52
cakephp在处理关联的时候如果不正确处理,会造成浪费很大资源,把很多没有用的数据一起取出来作为数组,在这点上我还是觉得django做的好,它只是把关联的地方作为对象返回来,而不是直接把所有关联的数据取出来
作者: yangchaohi    时间: 2009-11-05 22:25
cakephp不了解,学习了,ORM用的比较少,自己手写比较多~




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2