简体   繁体   English

Laravel 4,凌乱的口才连接查询

[英]Laravel 4, messy Eloquent join query

I'm working on somehow messy project where structure of db is: 我正在某种程度上的db结构的混乱项目:

Object
id, title, description, url ... [and some more columns]

ObjectMeta
object_id, variable, value

So let's give you: 因此,让我们给您:

Object: 1, 'Cool Book', 'This cool book is just for you!', ...

Object Meta:
1, 'author_name', 'John Doe'
1, 'released', 2014
1, 'price', 23.22
1, 'url', 'http://amazon.com/coolbook'
1, 'genre', 3

So I need to perform query which will: 因此,我需要执行以下查询:

Pull all Objects that has genre 3, then sort those Objects by their released date. 提取所有类型为3的对象,然后按发布日期对这些对象进行排序。

$objs = static::Active()
->where('object', '=', $object)
->where('category','=',$category)
->whereIn('site_id', array(self::$site_id, 0))
->leftJoin('object_meta', function($join)
{
  $join->on('object.id','=', 'object_meta.content_id');
})
->where('object_meta.variable', 'genre')
->where('object_meta.value', 3);
->where('object_meta.variable', 'released');
->orderBy('object_meta.value', 'desc');
->groupBy('object.id')
->paginate(20);

This query has 0 results even if there are plenty of those books out there. 即使有很多这些书,此查询也会有0个结果。 I know that the second object_meta.variable where is guilty here. 我知道第二个object_meta.variable在这里有罪。 How can I write this query to make it work? 如何编写此查询以使其正常工作?

Really appreciating your help. 非常感谢您的帮助。

-- Edit -编辑

I've created workaround but it's really, really bad workaround (funny thing is that I swear the query above was working for month or so). 我已经创建了变通办法,但这确实是非常糟糕的变通办法(有趣的是,我发誓上面的查询工作了一个月左右)。

$objs = static::Active()
->where('object', '=', $object)
->where('category','=',$category)
->whereIn('site_id', array(self::$site_id, 0))
->leftJoin('object_meta', function($join)
{
  $join->on('object.id','=', 'object_meta.content_id');
})
->where('object_meta.variable', 'genre')
->where('object_meta.value', 3);
->groupBy('object.id')
->get();

foreach($objs as $obj)
{
  $obj->id = $obj->object_id;
    $objs_meta = ObjectMeta::where('object_id',$obj->object_id)->get();
    foreach($objs_meta as $obj_meta)
    {
      $variable = $obj_meta->var;
      $obj->$variable = $obj_meta->value;
    }
}
$objs = $objs->sortBy(function($role){
  return $role->released;
});
$objs = Paginator::make($objs->toArray(), sizeof($objs), $limit);

You need inner join ( join() ) not leftJoin() , and you need it twice: 您需要内部连接( join() )而不是leftJoin() ,并且需要两次:

$objs = static::Active()
 ->where('object', '=', $object)
 ->where('category','=',$category)
 ->whereIn('site_id', array(self::$site_id, 0))

 ->join('object_meta as genre', function ($join) {
   $join->on('object.id', '=', 'genre.content_id')
      ->where('genre.variable', '=', 'genre')
      ->where('genre.value', '=', 3);
 })
 ->join('object_meta as released', function ($join) {
   $join->on('object.id', '=', 'released.content_id')
      ->where('released.variable', '=', 'released');
 })

 ->orderBy('released.value', 'desc');
 ->select('object.*', 'released.value as released')

 ->distinct()
 // or group by, doesn't matter in your case
 // ->groupBy('object.id')

 ->paginate(20);

Then your objects will have additional property released with appropriate value. 然后,您的对象将released具有适当值的其他属性。


According to the comments: 根据评论:

If you want to dynamically add the joins, then I suggest scopes like below: 如果要动态添加联接,则建议使用如下范围:

public function scopeGenre($query, $value)
{
   $query->join('object_meta as genre', function ($join) use ($value) {
       $join->on('object.id', '=', 'genre.content_id')
          ->where('genre.variable', '=', 'genre')
          ->where('genre.value', '=', $value);
     });
}

then: 然后:

$query->where(..)->genre(3)->...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM