Я пытаюсь решить проблему с Laravel 5.1 Eloquent Query Builder, где разбиение на страницы нарушает SQL, когда Query Builder содержит RAW Selects.
Я создаю веб-приложение, где пользователь может запросить список профилей. Внешний интерфейс имеет пользовательский интерфейс фильтрации. Пользовательский интерфейс фильтрации имеет опцию для «содержит 1 или более изображений» а также «содержит 1 или более видео».
База данных MySQL имеет таблицу для профилей и отдельную таблицу для элементов мультимедиа (изображений, видео и т. Д.). В таблице «Медиа» есть столбец «Идентификатор профиля» (владелец) и столбец типа медиа (представляющий изображение, видео и т. Д.).
Поэтому я пытаюсь подсчитать количество элементов мультимедиа, которые соответствуют идентификатору профиля, а затем оценить, если количество> 1.
Есть также другие опции фильтрации, которые являются простыми операторами WHERE в таблице профиля (однако они работают нормально) — например. пол, доб и т.д.
Я добавил следующий метод в мою модель профиля 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;
}
// $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-запрос прекрасно работает в 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. Другие вопросы переполнения стека инструктируют вручную создавать нумерацию страниц, однако примеры были на уровне 4, с использованием методов, которые, кажется, не существуют в 5.1
Пожалуйста помоги.
Спасибо Зак
Задача ещё не решена.
Других решений пока нет …