В Laravel 6 У меня есть запрос объявлений с количеством связанных изображений
$ads = Ad
->getByTitle($this->filter_title)
->onlyNoneInfo()
->getByStatus('A')
//->imagesCount(true)
->getUserByStatus('A')
->leftJoin('users', 'users.id', '=', 'ads.creator_id')
->orderBy($this->order_by, $this->order_direction)
->select(
'ads.*',
'users.name as creator_username',
'users.email as creator_email',
'users.phone as creator_phone'
)->addSelect(['ad_images_count' => AdImage
::selectRaw('count(*)')
->whereColumn('ad_images.ad_id', 'ads.id')
])
->offset($limit_start)
->take($ads_per_page)
->distinct()
->paginate($ads_per_page);
, и я вижу поле sql
request ad_images_count
:
SELECT distinct `sda_ads`.*, `sda_users`.`name` AS `creator_username`, `sda_users`.`email` AS `creator_email`, `sda_users`.`phone` AS `creator_phone`, ( SELECT count(*)
FROM `sda_ad_images`
WHERE `sda_ad_images`.`ad_id` = `sda_ads`.`id`) AS `ad_images_count`
FROM `sda_ads`
LEFT JOIN `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id`
WHERE `ad_type` <> 'I' AND `sda_ads`.`status` = 'A' AND `sda_users`.`status` = 'A'
ORDER BY `price` asc limit 4 offset 0
и оно у меня работает с действительным значением в ad_images_count
. Мне нужно установить фильтр, чтобы показывать только рекламу с изображениями, и я добавил область в App Model
:
public function scopeImagesCount($query, bool $check_images_count)
{
if ($check_images_count) {
return $query->where('ad_images_count', '>', 0);
}
return $query;
}
Но если раскомментировать строку в запросе:
//->imagesCount(true)
Я получил ошибка:
МОДИФИЦИРОВАННЫЙ БЛОК: С запросом, в котором я прокомментировал подзапрос ad_images_count:
$ads = Ad
::getByTitle($this->filter_title)
->onlyNoneInfo()
->getByStatus('A')
->getUserByStatus('A')
->imagesCount(true)
->leftJoin('users', 'users.id', '=', 'ads.creator_id')
->orderBy($this->order_by, $this->order_direction)
->select(
'ads.*',
'users.name as creator_username',
'users.email as creator_email',
'users.phone as creator_phone'
)
/*
->addSelect(['ad_images_count' => AdImage
::selectRaw('count(*)')
->whereColumn('ad_images.ad_id', 'ads.id')
])
*/
->offset($limit_start)
->take($ads_per_page)
->distinct()
->paginate($ads_per_page);
Я изменил область видения с ведением журнала:
public function scopeImagesCount($query, bool $check_images_count)
{
\Log::info('scopeImagesCount $check_images_count ::');
\Log::info($check_images_count);
if ($check_images_count) {
\Log::info('CHECKING ::');
return $query->select(['ad_images_count' => AdImage
::selectRaw('count(*)')
->whereColumn('ad_images.ad_id', 'ads.id')
])->where('ad_images_count', '>', 0);
}
\Log::info('SKIPPED CHECKING ::');
return $query;
}
И я вижу журнал и неизвестную ошибку столбца в файле журнала:
[2020-01-30 11:29:59] local.INFO: scopeImagesCount $check_images_count ::
[2020-01-30 11:29:59] local.INFO: 1
[2020-01-30 11:29:59] local.INFO: CHECKING ::
[2020-01-30 11:29:59] local.ERROR: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ad_images_count' in 'where clause' (SQL: select count(*) as aggregate from `sda_ads` left join `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` where `ad_type` <> I and `sda_ads`.`status` = A and `sda_users`.`status` = A and `ad_images_count` > 0) {"exception":"[object] (Illuminate\\Database\\QueryException(code: 42S22): SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ad_images_count' in 'where clause' (SQL: select count(*) as aggregate from `sda_ads` left join `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` where `ad_type` <> I and `sda_ads`.`status` = A and `sda_users`.`status` = A and `ad_images_count` > 0) at /mnt/_work_sdb8/wwwroot/lar/ads-backend-api/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669)
В результате sql нет подзапроса с ad_images_count Что не так?
МОДИФИЦИРОВАННЫЙ БЛОК № 2:
Если комментировать imagesCount с запросом
$ads = Ad
::getByTitle($this->filter_title)
->onlyNoneInfo()
->getByStatus('A')
->getUserByStatus('A')
// ->imagesCount(true)
->leftJoin('users', 'users.id', '=', 'ads.creator_id')
->orderBy($this->order_by, $this->order_direction)
->select(
'ads.*',
'users.name as creator_username',
'users.email as creator_email',
'users.phone as creator_phone'
)
->addSelect(['ad_images_count' => AdImage
::selectRaw('count(*)')
->whereColumn('ad_images.ad_id', 'ads.id')
])
->offset($limit_start)
->take($ads_per_page)
->distinct()
->paginate($ads_per_page);
Я вижу sql сгенерировано:
SELECT distinct `sda_ads`.*, `sda_users`.`name` AS `creator_username`, `sda_users`.`email` AS `creator_email`, `sda_users`.`phone` AS `creator_phone`, ( SELECT count(*)
FROM `sda_ad_images`
WHERE `sda_ad_images`.`ad_id` = `sda_ads`.`id`) AS `ad_images_count`
FROM `sda_ads`
LEFT JOIN `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id`
WHERE `ad_type` <> 'I' AND `sda_ads`.`status` = 'A' AND `sda_users`.`status` = 'A'
ORDER BY `price` asc limit 4 offset 0
с полем ad_images_count, имеющим действительное значение
Если раскомментировать imagesCount с областью действия:
public function scopeImagesCount($query, bool $check_images_count)
{
\Log::info('scopeImagesCount $check_images_count ::');
\Log::info($check_images_count);
if ($check_images_count) {
\Log::info('CHECKING ::');
return $query->select(['ad_images_count' => AdImage
// return $query->addSelect(['ad_images_count' => AdImage
::selectRaw('count(*)')
->whereColumn('ad_images.ad_id', 'ads.id')
])->where('ad_images_count', '>', 0);
}
\Log::info('SKIPPED CHECKING ::');
return $query;
}
Я получил ошибку:
[2020-01-31 15:27:37] local.ERROR: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ad_images_count' in 'where clause' (SQL: select count(*) as aggregate from `sda_ads` left join `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` where `ad_type` <> I and `sda_ads`.`status` = A and `sda_users`.`status` = A and `ad_images_count` > 0) {"exception":"[object] (Illuminate\\Database\\QueryException(code: 42S22): SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ad_images_count' in 'where clause' (SQL: select count(*) as aggregate from `sda_ads` left join `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` where `ad_type` <> I and `sda_ads`.`status` = A and `sda_users`.`status` = A and `ad_images_count` > 0) at /mnt/_work_sdb8/wwwroot/lar/ads-backend-api/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669)
Я пытался использовать addSelect - та же ошибка. Похоже на необходимость повторять подзапрос, но не имя столбца. Как?
МОДИФИЦИРОВАННЫЙ БЛОК № 3: Я пытаюсь использовать:
$prefix= DB::getTablePrefix();
$ads = Ad
::getByTitle($this->filter_title)
->onlyNoneInfo()
->getByStatus('A')
->getUserByStatus('A')
->leftJoin('users', 'users.id', '=', 'ads.creator_id')
->orderBy($this->order_by, $this->order_direction)
->select(
'ads.*',
'users.name as creator_username',
'users.email as creator_email',
'users.phone as creator_phone'
)
->addSelect(['ad_images_count' => AdImage
::selectRaw('count(*)')
->whereColumn('ad_images.ad_id', 'ads.id')
])
->offset($limit_start)
->take($ads_per_page)
->havingRaw(' ( SELECT count(*) '.
' FROM `'.$prefix.'ad_images'.'` '.
' WHERE '.$prefix.'ad_images.ad_id = `'.$prefix.'ads`.`id` ) > ?', [0])
->paginate($ads_per_page)
, но я получил ошибку:
Unknown column 'ads-backend-api.sda_ads.id' in 'where clause' (SQL:
select count(*) as aggregate from `sda_ads` left join `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` where `ad_type` <> I and `sda_ads`.`status` = A and `sda_users`.`status` = A having ( SELECT count(*) FROM `sda_ad_images` WHERE sda_ad_images.ad_id = `sda_ads`.`id` ) > 0
Похоже sda_ads
. id
недопустимое условие. Какой тип обтекания ему нужен?
Я также пробовал без переноса символа «` »как:
->havingRaw(' ( SELECT count(*) '.
' FROM `'.$prefix.'ad_images'.'` '.
' WHERE '.$prefix.'ad_images.ad_id = '.$prefix.'ads.id ) > ?', [0])
и получил:
Unknown column 'ads-backend-api.sda_ads.id' in 'where clause' (SQL: select count(*) as aggregate from `sda_ads` left join `sda_users` on `sda_users`.`id` = `sda_ads`.`creator_id` where `ad_type` <> I and `sda_ads`.`status` = A and `sda_users`.`status` = A having ( SELECT count(*) FROM `sda_ad_images` WHERE sda_ad_images.ad_id = sda_ads.id ) > 0
В моей рекламе базы данных -backend-api У меня есть таблица sda_ads с полем id.
«sda_» - это префикс db в конфигурации базы данных.
Какой путь подходит?
Спасибо!