Упорядочить wp_query по вычисляемому полю

Вопрос или проблема

Привет, я работаю над локатором магазинов.
У меня есть пользовательская запись “клиники”, где я сохраняю детали клиники (адрес, .., широта, долгота). Каждый раз, когда я публикую новую клинику, я также сохраняю post_id, широту и долготу в пользовательской таблице “lat_lng_post”.

Я могу искать клиники в пределах определенного расстояния, используя фильтр post_where следующим образом:

add_filter( 'posts_where' , 'location_posts_where' )


    function location_posts_where( $where )
        {
            // $lat и $lng - это широта и долгота искомой точки
            global $wpdb;    
            $where .= " AND $wpdb->posts.ID IN (SELECT post_id FROM lat_lng_post 
                 WHERE
                 (6371 * acos( cos( radians(" . $lat . ") )
                  * cos( radians( lat ) )
                  * cos( radians( lng )
                  - radians(" . $lng . ") )
                  + sin( radians(" . $lat . ") )
                  * sin( radians( lat ) ) ) ) <= 150 
                    ORDER BY 
                        ( 6371 * acos( cos( radians(" . $lat . ") )
                  * cos( radians( lat ) )
                  * cos( radians( lng )
                  - radians(" . $lng . ") )
                  + sin( radians(" . $lat . ") )
                  * sin( radians( lat ) ) ) ) ASC)";
                        return $where;
                    }

Я получаю клиники в пределах фиксированного расстояния (150 км), но они не упорядочены по расстоянию. Они показываются в порядке даты публикации.
Я попытался установить orderby на none:

$args = array (
    'post_type'              => 'clinica',
    'orderby'                => 'none'

);

Но это не сработало. Как я могу заставить упорядочить по тому правилу ORDER BY, которое я установил в запросе?

Используя WP_Query, вы можете упорядочить результаты по meta_value_num:

$args = array (
    'post_type' => 'clinica',
    'meta_key'  => 'distance_field_name',
    'orderby'   => 'meta_value_num',
    'order'     => 'DESC'
);

Ответ или решение

Для решения проблемы сортировки результатов WP_Query по вычисленному полю расстояния между точками, необходимо внести некоторые изменения в вашу реализацию. Данный подход позволит вам получить список клиник, отсортированных по близости к определенной точке, используя параметры запроса и фильтры WordPress.

Введение

Вы хотите отображать клиники, которые находятся в определенном радиусе от заданной точки, и сортировать их по расстоянию. Ваша текущая реализация находит клиники, но сортировка осуществляется по дате публикации. Это можно исправить, добавив вычисляемое поле для расстояния в запрос.

Решение

Шаг 1: Расчет расстояния

Прежде всего, вы можете вычислить расстояние до каждой клиники в подзапросе, который будет присоединяться к основному запросу. Для этого вам нужно будет расширить ваш фильтр posts_where так, чтобы возвращать не только подходящие клиники, но и расстояние до них.

Шаг 2: Использование posts_orderby

Добавьте следующий код в файл вашей темы или в плагин:

add_filter( 'posts_orderby', 'location_posts_orderby' );

function location_posts_orderby( $orderby ) {
    global $wpdb;

    // Добавляем вычисленное поле расстояния в оператор ORDER BY
    $orderby = "( 6371 * acos( cos( radians(" . $lat . ") )
          * cos( radians( lat ) )
          * cos( radians( lng )
          - radians(" . $lng . ") )
          + sin( radians(" . $lat . ") )
          * sin( radians( lat ) ) ) ) ASC";

    return $orderby;
}

Шаг 3: Изменение вашего основного запроса

Теперь вам нужно изменить ваш основной запрос, добавив правильные параметры для сортировки:

$args = array(
    'post_type'      => 'clinica',
    'posts_per_page' => -1, // или любое другое количество
);

// Получите широту и долготу
$lat =  /* Ваши координаты широты */;
$lng =  /* Ваши координаты долготы */;

add_filter( 'posts_where', 'location_posts_where' );
add_filter( 'posts_orderby', 'location_posts_orderby' );

$query = new WP_Query( $args );

// не забудьте снять фильтры после использования
remove_filter( 'posts_where', 'location_posts_where' );
remove_filter( 'posts_orderby', 'location_posts_orderby' );

Шаг 4: Дополнительные меры

  1. Оптимизация производительности: Убедитесь, что ваша база данных индексирована для повышения производительности запросов, связанных с геолокацией. Используйте методы кэширования для уменьшения нагрузки на сервер, особенно если у вас много клиник.

  2. Использование мета-полей: Вместо вычисления расстояния в каждом запросе, вы также можете сохранять рассчитанное расстояние в мета-поле. Это может упростить ваши запросы, но потребует дополнительной логики для обновления этих значений в случае изменения местоположения клиники.

Заключение

С помощью вышеуказанных шагов вам удастся упорядочить результаты WP_Query на основе расстояния до заданной точки. Это значительно улучшит функциональность вашего магазина-локатора и принесет большую пользу пользователям, поскольку они смогут легче находить ближайшие клиники. Использование корректных фильтров и методов сортировки – ключ к созданию эффективного решения.

Оцените материал
Добавить комментарий

Капча загружается...