#laravel #laravel-4 #eloquent
#laravel #laravel-4 #eloquent
Вопрос:
У меня есть две таблицы, магазины и местоположения.
Прямо сейчас я делаю это:
$shops = Shop::with('location');
if (Input::has('location')) {
$shops->whereHas('location', function($q) use ($input) {
$q->where('name', '=', Input::get('location');
});
}
return $shops->paginate(10);
и все идет нормально.
Тем не менее, я хотел бы также включить значение расстояния и упорядочить по нему. В основном это сводится к созданию вычисленного значения, которое я пытался сделать следующим образом:
$shops->raw('(
3959 * acos (
cos ( radians(?) )
* cos( radians( locations.lat ) )
* cos( radians( locations.lon ) - radians(?) )
sin ( radians(?) )
* sin( radians( locations.lat ) )
)
) AS distance
', array(Session::get('latitude'), Session::get('longitude'), Session::get('latitude')));
(ставится перед возвращаемым значением выше)
Это ничего не делает — замена на whereRaw также не работает.
Мне придется прекратить использовать Eloquent (снова!), Или с этим может справиться Eloquent?
Комментарии:
1. 2. Вы должны подключить событие eloquent и распечатать фактический SQL, сгенерированный вашей функцией, — тогда вы сможете отладить происходящее.
2. Это весь код, я не определил
raw
функцию конкретно. Запрос не изменяется при его использовании (возможно, потому, что он не существует?). Использование whereRaw вызывает исключение.3. Я думаю вслух, что, поскольку вы выполняете вычисляемую функцию , вам, вероятно, нужно включить
raw()
при первоначальном вызове Shop . Так что, может быть, что-то вроде$shops = Show::with('location')->raw(<code>)
4. Кажется, что
whereRaw
всегда помещает код послеWHERE
оператора в SQL, что, я думаю, логично. Я не могу понять, как это сделать раньше, я думаю, это сработало бы, если бы я мог…5. Может, вы просто используете raw()? Также — проверьте этот пример — вы могли бы попробовать select() с DB::raw() — laravel.com/docs/queries#raw-expressions
Ответ №1:
- Вам нужно
selectRaw
илиselect(DB::raw(...))
, неwhereRaw
- Вам нужно присоединиться
locations
к таблице, чтобы выбрать из нее (чтобы привязать расстояние кShop
объектам) ИЛИ поместите эту часть вLocation
модели загрузки запросов (для привязки расстояния кLocation
объектам):Shop::with(['location' => function ($q) { $q->selectRaw(' *, YOUR_CALC_HERE as distance'); // don't forget to select all with '*' }]);
Если вы хотите упорядочивать магазины по расстоянию, то вам определенно нужно объединение.
Ответ №2:
После некоторой помощи по IRC я решил сделать это именно так:
// First, specify a manual join onto locations, so the values are available in this query
$shops->join('locations', 'shops.location_id', '=', 'locations.id');
// Second, add the selectRaw (which seems to not have variable binding?)
$shops->selectRaw('(
3959 * acos (
cos ( radians('.Session::get('latitude').') )
* cos( radians( locations.lat ) )
* cos( radians( locations.lon ) - radians('.Session::get('longitude').') )
sin ( radians('.Session::get('latitude').') )
* sin( radians( locations.lat ) )
)
) AS distance
');
// select the rest of the variables on shops afterwards to avoid any name collisons
$shops->addSelect('shops.*');