【问题标题】:In Laravel 4 how to query ManyToMany relationships?在 Laravel 4 中如何查询多对多关系?
【发布时间】:2013-03-05 10:30:05
【问题描述】:

在 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 的所有项目,但是它没有返回任何东西!

有什么帮助吗?

【问题讨论】:

  • 您可以在页面底部看到 config/application.php 中设置 profiler = true 后执行的 sql 查询。之后,如果您可以共享 sql quaries,我们可以更有效地为您提供帮助。

标签: php orm laravel laravel-4 eloquent


【解决方案1】:

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

如果您解决了上述问题,那么您应该能够正确访问数据透视表。

我认为问题在于您需要加入标签 id 而不是商品 id。

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

【讨论】:

    【解决方案2】:

    我猜您正在寻找内部连接?试试这个:

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

    【讨论】:

      【解决方案3】:

      我终于找到了答案!

      使用“haveRaw”将解决问题

      “列表”也为我们提供标签表中标签的 ID

      注意:“haveRaw”仅在 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,这是因为使用“joins”会导致歧义, 要解决这个问题,您必须添加以下选择语句

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

      【讨论】:

      • 我无法运行,也无法理解更新,可以解释一下吗?
      • 好的,我完成了 50% 的代码。 Laravel 在我的数据库中找不到 foo bar 标签会引发 sql 错误原因。我处理了。但现在我需要你的更新。正如您提到的 $entry->id 返回标签 ID。我的模型也在使用@foreach($entry->tags as $tag),但现在这个也不起作用了。
      • Laravel 4.1 带来了 wherePivot / orWherePivot 原生方法就是为了这个目的。无需再为这些烦恼。
      • @Arda wherePivot 可以为每个项目搜索多个标签搜索。我的意思是一个项目必须包含我搜索的所有标签,而不是其中一个。
      • @alayli 是的,然后使用多个 wherePivot 子句。
      猜你喜欢
      • 1970-01-01
      • 2018-11-02
      • 2015-05-29
      • 1970-01-01
      • 2019-03-28
      • 1970-01-01
      • 2019-02-07
      • 2020-12-15
      • 1970-01-01
      相关资源
      最近更新 更多