我正在尝试解决 Laravel 5.1 Eloquent Query Builder 的问题,当 Query Builder 包含 RAW Selects 时,分页会破坏 SQL。
背景
我正在构建一个 Web 应用程序,用户可以在其中查询配置文件列表。前端有一个过滤 UI。过滤 UI 有“包含 1 个或多个图像”和“包含 1 个或多个视频”的选项。
MySQL 数据库有一个用于配置文件的表,以及一个用于媒体项目(图像、视频等)的单独表。Media 表有一个 Profile ID 列(所有者)和一个媒体类型列(表示图像、视频等)。
因此,我试图计算与配置文件 ID 匹配的媒体项目的数量,然后评估计数是否 > 1。
还有其他过滤选项是 Profile 表上的简单 WHERE 语句(但是这些都可以正常工作) - 例如。性别,出生日期等...
我在我的 laravel Profile 模型中添加了以下方法:
public function scopeMediaCounts($query, $media_type, $count = null, $operator = '=')
{
$media_types = array();
switch ($media_type) {
case 'images':
$media_types[] = 1;
break;
case 'videos':
$media_types[] = 2;
$media_types[] = 3;
break;
}
// $query to build
}
我打算这样使用它:->mediaCounts('images', 1, '>')->mediaCounts('videos', 1, '>')
我试过的
我已经尝试了基于 laravel 文档、堆栈溢出答案、谷歌搜索和反复试验的各种组合。但是我能得到的最接近的是:
public function scopeMediaCounts($query, $media_type, $count = null, $operator = '=')
{
$media_types = array();
switch ($media_type) {
case 'images':
$media_types[] = 1;
break;
case 'videos':
$media_types[] = 2;
$media_types[] = 3;
break;
}
$types = implode(',', $media_types);
$query->leftJoin('media', 'profiles.profile_id', '=', 'media.profile_id')
->selectRaw("profiles.*, count(media.profile_id) as {$media_type}Count")
->whereIn('media.type', $media_types)
->groupBy('profiles.profile_id');
if (is_int($count))
$query->having("{$media_type}Count", $operator, $count);
return $query;
}
当尝试使用->mediaCounts()
不止一次时,上面的代码会中断。
哎呀,看起来像出事了。
2/2
QueryException in Connection.php line 662:
SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'media' (SQL: select profiles.*, count(media.profile_id) as imagesCount, profiles.*, count(media.profile_id) as videosCount from `profiles` left join `media` on `profiles`.`profile_id` = `media`.`profile_id` left join `media` on `profiles`.`profile_id` = `media`.`profile_id` where `media`.`type` in (1) and `media`.`type` in (2, 3) group by `profiles`.`profile_id`, `profiles`.`profile_id` having `imagesCount` >= 1 and `videosCount` >= 1)
public function scopeMediaCounts($query, $media_type, $count = null, $operator = '=')
{
$media_types = array();
switch ($media_type) {
case 'images':
$media_types[] = 1;
break;
case 'videos':
$media_types[] = 2;
$media_types[] = 3;
break;
}
$types = implode(',', $media_types);
$query
->selectRaw("{$this->table}.*, ( SELECT COUNT(*)
FROM ver3_data_media media
WHERE media.profile_id = {$this->table}.profile_id
) AS \"{$media_type}Count\"")
->having("{$media_type}Count", $operator, $count);
return $query;
}
上面的示例没有考虑媒体类型,但在传递到分页函数之前“有效”。
错误: ->mediaCounts('images', 1, '>')->mediaCounts('videos', 1, '>')->paginate(20)
QueryException in Connection.php line 662:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'imagesCount' in 'having clause' (SQL: select count(*) as aggregate from `profiles` having `imagesCount` >= 1 and `videosCount` >= 1)
但是,如果我在 SQL 到达分页之前转储 SQL,SQL 查询在 MySQL Workbench 中工作正常(减去它不选择媒体类型):
select profiles.*, ( SELECT COUNT(*)
FROM media media
WHERE media.profile_id = profiles.profile_id
) AS imagesCount, profiles.*, ( SELECT COUNT(*)
FROM media media
WHERE media.profile_id = profiles.profile_id
) AS videosCount from `profiles` group by `profiles`.`profile_id`, `profiles`.`profile_id` having `imagesCount` >= 1 and `videosCount` >= 1
真的不知道如何解决分页问题。其他堆栈溢出问题指示手动创建分页,但是示例是 laravel 4,使用 5.1 中似乎不存在的方法
请帮忙。
谢谢,扎克