在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”和“bar”的项目?只返回同时包含两个标签的商品!?
我已经尝试过以下但它对我不起作用,我觉得问题出在“ - > having”条款但是我无法做到正确,
让我们假设标签“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的所有项目,但它不会返回任何内容!
任何帮助?
答案 0 :(得分:4)
最后我找到了答案!
使用“havingRaw”将解决问题
同样“list”为我们提供标签表
中标签的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!,而是包含tags.id,这是因为使用“join”会导致歧义, 要解决这个问题,你必须添加以下select语句
->select('items.id as id','items.name as name')
答案 1 :(得分:1)
对于ManyToMany关系,两个Eloquent类都需要返回$this->belongsToMany
。在您的Tag类中,您使用的是不使用数据透视表的hasMany。
如果您修复了上述问题,那么您应该能够正确访问数据透视表。
我认为问题在于您需要加入标签ID而不是商品ID。
return static::leftJoin(
'item_tag',
'tags.id', '=', 'item_tag.tag_id'
)
答案 2 :(得分:1)
我猜你正在寻找内联?试试这个:
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));
}
}