Laravel 4,凌乱的 Eloquent 连接查询
Posted
技术标签:
【中文标题】Laravel 4,凌乱的 Eloquent 连接查询【英文标题】:Laravel 4, messy Eloquent join query 【发布时间】:2014-07-23 12:48:49 【问题描述】:我正在做一些杂乱无章的项目,其中 db 的结构是:
Object
id, title, description, url ... [and some more columns]
ObjectMeta
object_id, variable, value
所以让我们给你:
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
所以我需要执行以下查询:
拉出所有类型为 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);
即使有很多这样的书,这个查询也有 0 个结果。我知道这里的第二个 object_meta.variable 是有罪的。如何编写此查询以使其正常工作?
非常感谢您的帮助。
-- 编辑
我已经创建了解决方法,但它确实是非常糟糕的解决方法(有趣的是,我发誓上面的查询已经工作了一个月左右)。
$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);
【问题讨论】:
对于->where('object_meta.variable', 'released');
,您正在尝试查找variable
等于genre
和released
的列?这可能是它返回 0 行的原因。
调试查询的第一件事是查看DB::getQueryLog()
日志,了解正在构建的查询。您也可以 ->toSql() 并使用即控制台直接针对数据库运行该查询。
是的,我知道这个问题。通过控制台对数据库运行时,查询不起作用。我真正想要的是以某种方式将“META.VAR”和“META.VALUE”信息注入我的“OBJECT”。所以我可以直接调用object.released、object.author、object.url,结果我会得到“META.VALUE”。
【参考方案1】:
你需要内连接 (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);
然后您的对象将具有附加属性released
并具有适当的值。
根据cmets:
如果你想动态添加连接,那么我建议如下范围:
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);
);
然后:
$query->where(..)->genre(3)->...
【讨论】:
这就是我想要的! PS。有没有办法在 X 连接中包含 X 变量(基本上是每个 MetaObject),这样我就可以使用所有其他属性?用户可以定义“流派”、“发布”等变量。 你的意思是像那些加入的动态数量? 是的。基本上,书籍有大约 6 个元对象(流派、网址、价格等),而音乐或视频有更多元对象(大约 10 个)。我可以在需要时手动添加连接,但查询拉出所有 MetaObject 会很好。使用您的代码,我将能够使用genre.value 和released.value,但是对于url.value,我需要进行另一个连接。 请不要再介意了!在这个加入问题上工作了 3 个小时后,我无法正确思考。用简单的 foreach 和使用参数解决它 -> pastebin.com/Na7tgckT以上是关于Laravel 4,凌乱的 Eloquent 连接查询的主要内容,如果未能解决你的问题,请参考以下文章
使用 Laravel 4 Eloquent 连接列上的列名“”无效?
如何使用 eloquent 在 laravel 中编写多个连接