#php #mysql #laravel #eloquent
#php #mysql #laravel #красноречивый
Вопрос:
У меня есть следующая настройка: posts
таблица, post_pics
таблица и post_post_pictures
таблица, которая действует как связующая таблица между сообщениями и post_pics
. В одном сообщении может быть несколько фотографий. Я хотел бы выбрать все изображения, принадлежащие этому сообщению, и вернуть их в виде массива для каждого сообщения (пример данных внизу вопроса).
Настройка таблиц следующая:
Публикации:
-------------- ----------------- ------ ----- --------- -------
| Field | Type | Null | Key | Default | Extra |
-------------- ----------------- ------ ----- --------- -------
| id | char(36) | NO | PRI | NULL | |
| ............... Other fields not important .................. |
| |
-------------- ----------------- ------ ----- --------- -------
post_pics:
--------- -------------- ------ ----- --------- -------
| Field | Type | Null | Key | Default | Extra |
--------- -------------- ------ ----- --------- -------
| id | char(36) | NO | PRI | NULL | |
| picture | varchar(255) | NO | | NULL | |
--------- -------------- ------ ----- --------- -------
post_post_pictures:
----------------- ---------- ------ ----- --------- -------
| Field | Type | Null | Key | Default | Extra |
----------------- ---------- ------ ----- --------- -------
| post_id | char(36) | NO | MUL | NULL | |
| post_picture_id | char(36) | NO | MUL | NULL | |
----------------- ---------- ------ ----- --------- -------
У меня есть следующий запрос, в котором я выбираю записи в заданном диапазоне на основе некоторых координат (эта часть работает нормально) — у меня возникли проблемы с выбором всех фотографий, которые есть в каждом сообщении, и возвращением этих фотографий в одной записи «post».
Соединения, которые я выполняю post_post_pictures
, и post_pics
, я думаю, неправильные / неполные.
$meanRadiusOfEarthInMiles = 3959;
$poiSearchDistanceInMiles = 60;
$clientLatitude = floatval($request->get('latitude'));
$clientLongitude = floatval($request->get('longitude'));
$posts = Post::select(
'posts.*',
'users.id as user_id',
'users.photo as company_photo',
'users.name as company_name',
'post_pics.picture as images'
)
->join('users', 'posts.user_id', '=', 'users.id') // This is incomplete I think
->join('post_post_pictures', 'posts.id','=', 'post_id') // and this one, I think
->join('post_pics', 'post_post_pictures.post_id','=', 'post_id')
->where('active', '=', '1')
->where('account_type', '=', 'business')
->selectRaw("($meanRadiusOfEarthInMiles *
acos(cos(radians(?)) * cos(radians(latitude)) *
cos(radians(longitude) - radians(?))
sin(radians(?)) * sin(radians(latitude)))
) AS miles_away", [$clientLatitude, $clientLongitude, $clientLatitude])
->havingRaw("miles_away < ?", [$poiSearchDistanceInMiles])
->get();
Приведенный выше запрос возвращает почти правильные данные, но похоже, что он возвращает одну строку для каждого изображения, вместо добавления всех изображений, принадлежащих записи, в эту запись.
Например, прямо сейчас я получаю много таких записей:
{
"id": "0792c20e-498c-4aa7-a2b2-f06f4775dc82",
"title": "test",
"description": "test",
"location": "<location name>",
"latitude": "<some lat>",
"longitude": "<some lon>",
"user_id": "271564de-35fa-4023-9b13-f68d0e9100d0",
"images": "<URL>/<IMAGE 1>",
"miles_away": 5.313459784530729
},
и я надеюсь, что смогу возвращать строки, подобные этой:
{
"id": "0792c20e-498c-4aa7-a2b2-f06f4775dc82",
"title": "test",
"description": "test",
"location": "<location name>",
"latitude": "<some lat>",
"longitude": "<some lon>",
"user_id": "271564de-35fa-4023-9b13-f68d0e9100d0",
"images": ["<URL>/<IMAGE 1>", "<URL>/<IMAGE 2>", ...], // return all images for the post as array would be ideal
"miles_away": 5.313459784530729
},
Возможно ли это? Я хочу вернуть его таким образом, поскольку клиентскому приложению легко работать.
Комментарии:
1. dba.stackexchange.com/questions/159765 /… может быть полезно
2. Ах да, вероятно, требуется что-то вроде включения
DB::raw('GROUP_CONCAT(post_pics.picture) as images')
в вызов toPost::select
. Спасибо
Ответ №1:
Спасибо @Nick Maroulis за комментарий, который навел меня на правильный путь для решения этой проблемы.
Мой запрос в итоге выглядел так:
$posts = Post::select(
'posts.*',
'users.id as user_id',
'users.photo as company_photo',
'users.name as company_name',
DB::raw('GROUP_CONCAT(post_pics.picture) as images') // < ---- change
)
->join('users', 'posts.user_id', '=', 'users.id')
->join('post_post_pictures', 'posts.id','=', 'post_id')
->join('post_pics', 'post_post_pictures.post_picture_id','=', 'post_pics.id')
->where('active', '=', '1')
->where('account_type', '=', 'business')
->selectRaw("($meanRadiusOfEarthInMiles *
acos(cos(radians(?)) * cos(radians(latitude)) *
cos(radians(longitude) - radians(?))
sin(radians(?)) * sin(radians(latitude)))
) AS miles_away", [$clientLatitude, $clientLongitude, $clientLatitude])
->havingRaw("miles_away < ?", [$poiSearchDistanceInMiles])
->groupBy('post_post_pictures.post_id') // < ---- change
->get();
Что дает результат, аналогичный следующему:
{
"id": "c4df92c6-1abf-4aeb-974c-b06b75dd45d2",
"title": "test post",
"latitude": "...",
"longitude": "...",
"availability": "...",
....
"user_id": "62fa9a40-3bea-48e5-badb-87d2c8d2ce35",
"views": 1,
"images": "<URL 1>,<URL 2>", // comma seperated URLs for the images
"miles_away": 0.5339829289762683
}
Изображения в конечном итоге разделяются запятой, а не в массиве, когда я отправляю его обратно клиенту в формате JSON, но это нормально 🙂