Получить запрос queryScope с помощью метода whereHas для расчета расстояния по формуле haversine - PullRequest
0 голосов
/ 22 сентября 2018

У меня есть Модель продуктов, Модель магазинов, и Продукты принадлежат Магазинам, в модели магазинов у меня есть это:

public function scopeWithDistance($query,$lat,$lng){
    $q = $query;
    if($lat != 0 && $lng != 0){
        $raw = 'floor((floor(3959 * acos(cos(radians(:lat1)) * cos(radians(lat))
                * cos(radians(lng) - radians(:lng))
                + sin(radians(:lng2)) * sin(radians(lat)))
            )) * 1.609344) AS distance';

        return $query->selectRaw($raw, [
            'lat1' => $lat,
            'lng' => $lng,
            'lat2' => $lat,
        ]);
    }
    return $q;
}

Я мог бы легко получить атрибуты магазина плюс рассчитанное расстояние с помощью:

App\Store::withDistance(20.6008362,-100.3966416)->get();

in tinker.

Но когда я запускаю запрос, пытаясь получить Store :: withDistance через мою модель Product, он не возвращает мне поле расстояния: (

Мой запрос:

$query = Product::whereHas('mm_product')
        ->with(['media', 'category', 'master_category', 'store.user.user_data', 'store.user.media', 'tag'])
        ->whereHas('store', function ($q) use ($state_id, $shop_id, $lat, $lng) {
            if ($state_id && $shop_id == 0) {
                $q->where(function ($q) use ($state_id, $lat, $lng) {
                    $q->whereNotNull('lat')->whereNotNull('lng')->where('state_id', $state_id)->withDistance($lat, $lng);
                });

            }
        });

ПОМОГИТЕ МНЕ ПОЖАЛУЙСТА: '(

РЕДАКТИРОВАТЬ: я делаю так, потому что я хочу сделать orderBy и разбить на страницы результаты на основе расчета расстояния.

1 Ответ

0 голосов
/ 22 сентября 2018

Вы должны добавить свою функцию поиска расстояния в напряженной загрузке, тогда она вернется в виде поля.При добавлении к whereHas он фильтрует только результат.Так что лучше использовать повторно, вы можете сделать это следующим образом

Определить эту функцию в Store модели (я изменил код haversine)

public static function haversine($coordinates)
{
    return '(6371 * acos(cos(radians(' . $coordinates['latitude'] . ')) 
    * cos(radians(`lat`)) 
    * cos(radians(`lng`) 
    - radians(' . $coordinates['longitude'] . ')) 
    + sin(radians(' . $coordinates['latitude'] . ')) 
    * sin(radians(`latitude`))))';
}

public function scopeWithinDistance($query, $haversine, $radius = 5)
{
    return $query->select('id', 'user_id')
                 ->selectRaw("{$haversine} AS distance")
                 ->whereRaw("{$haversine} < ?", [$radius])
                 ->orderBy('distance');
}

Теперь используйте ее в своем запросе, как это

$haversine = Store::haversine(['latitude' => '20.6008362', 'longitude' => '-100.3966416']);

$query = Product::whereHas('mm_product')
        ->with(['media', 'category', 'master_category','store' => function($q) use($haversine){
             $q->selectRaw("*, {$haversine} AS distance");
         },'store.user.user_data', 'store.user.media', 'tag'])
        ->whereHas('store', function ($q) use ($state_id, $shop_id, $haversine) {
            if ($state_id && $shop_id == 0) {
                $q->where(function ($q) use ($state_id, $haversine) {
                    $q->whereNotNull('lat')->whereNotNull('lng')
                      ->where('state_id', $state_id)
                      ->withinDistance($haversine);
                });
            }
        });

Это даст вам расстояние в милях, если вы хотите, чтобы оно было в километрах, умножьте его на 1.60934

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...