在Laravel 4中如何查询many - many关系


In Laravel 4 how to query ManyToMany relationships?

在Laravel 4中我有以下表格

 - items table
 --- id
 --- name

 - tags table
 --- id
 --- name
 - item_tag
 --- id
 --- tag_id
 --- item_id
 --- created_at
 --- updated_at

class Item extends Eloquent {
    public function tags()
    {
        return $this->belongsToMany('Tag');
    }
}


class Tag extends Eloquent {
    public function items()
    {
       return $this->hasMany('Item');
    }
}

我的问题:

我想得到所有项目有以下两个标签"foo"answers"bar"?只有具有两个标签的项目才应该返回!?

<标题> 更新

我试过下面的,但它不适合我,我有一种感觉,问题是"->有"从句,但我不能得到它的权利,

让我们假设标签"foo"的id为1,"bar"的id为2

class Item extends Eloquent {
protected $table = 'items';
public function tags()
{
    return $this->belongsToMany('Tag');
}
 public static function withTags()
{
  return static::leftJoin(
    'item_tag',
    'items.id', '=', 'item_tag.item_id'
  )
  ->whereIn('item_tag.tag_id', array(1, 2))
   ->groupBy('items.id')
   ->having('count(*)', '=',2)
  ;
}   
}

和运行

   #routes.php
   Route::get('/', function()
   {
        return Item::withTags()->get();
   });

它应该返回标签为1和2的所有项目,但是它没有返回任何东西!

帮忙吗?

我终于找到了答案!

使用"havingRaw"将解决这个问题

还提供了标签表

中标签的id。

注意:"havingRaw"仅在Laravel 4- beta 4或更高版本中可用

class Item extends Eloquent {
protected $table = 'items';
public function tags()
{
    return $this->belongsToMany('Tag');
}
public static function withTags($tags = array())
{
    $count = count($tags);
    return static::leftjoin('item_tag', 'items.id', '=', 'item_tag.item_id')
        ->whereIn('item_tag.tag_id', Tag::whereIn('name', $tags)->lists('id'))
        ->groupBy('item_tag.item_id')
        ->havingRaw('count(*)='.$count)
        ;
}    
}

和运行

   return Item::withTags(['foo','bar'])->get();

更新:重要提示

当您看到上面代码的输出时,您会注意到item->id不包含items.id!,它将包含标签。这是因为使用"join"会产生歧义,要解决这个问题,您必须添加以下select语句

  ->select('items.id as id','items.name as name')

对于多对多关系,两个Eloquent类都需要返回一个$this->belongsToMany。在你的标签类中,你正在使用hasMany,它不使用数据透视表。

如果您修复了上面的问题,那么您应该能够正确访问数据透视表。

我认为问题是你需要加入标签id而不是项目id。

return static::leftJoin(
    'item_tag',
    'tags.id', '=', 'item_tag.tag_id'
)

我猜你正在寻找一个内连接?试试这个:

class Item extends Eloquent {
    protected $table = 'items';
    public function tags()
    {
        return $this->belongsToMany('Tag');
    }
    public static function withTags()
    {
        return static::join('item_tag', 'items.id', '=', 'item_tag.item_id')
            ->whereIn('item_tag.tag_id', array(1, 2));
    }   
}