Laravel 5.1 Eloquent Query Builder分页与Raw SQL打破

时间:2016-08-07 14:33:37

标签: php mysql laravel-5 pagination laravel-paginate

我试图解决Laravel 5.1 Eloquent Query Builder的问题,当查询生成器包含RAW选择时,分页正在破坏SQL。

背景

我正在构建一个Web应用程序,用户可以在其中查询个人档案列表。前端有一个过滤UI。过滤用户界面可以选择"包含一个或多个图片" "包含一个或多个视频"

MySQL数据库有一个用于配置文件的表,以及一个用于媒体项目(图像,视频等)的单独表格。 Media表具有Profile ID列(所有者)和媒体类型列(表示图像,视频等)。

因此,我尝试计算与个人资料ID匹配的媒体项目数量,然后评估计数是否>> 1.

还有其他过滤选项,它们是Profile表上的简单WHERE语句(但这些选项工作正常) - 例如。性别,dob等...

我已将以下方法添加到我的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文档,堆栈溢出答案,Google搜索以及试用版和试用版尝试了各种组合。错误。然而,我能得到的最接近的是:

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

上面的例子没有考虑媒体类型,但是"工作"直到它进入paginate函数。

错误: ->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到达Paginate之前转储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

真的不确定如何解决Paginate破解问题。其他堆栈溢出问题指示手动创建分页,但是示例是laravel 4,使用5.1中似乎不存在的方法

请帮忙。

谢谢,Zac

0 个答案:

没有答案