Intereting Posts
Отобразить изображение для категории с помощью get_categories или показать изображение из любого дочернего сообщения Можно ли переименовать поле описания в пользовательский тип сообщения? Импортируйте csv (6k строк), затем введите термин, метаболизм и сообщение Почему мой WordPress загружает старую версию JQuery? Ajax-вызов из single.php в файл плагина в бэкэнд Wesbite супер медленный на iphone / очень быстро на рабочем столе с тем же соединением на Wi-Fi Получение миниатюры в fetch_feed из настраиваемого поля Как изменить высоту изображения заголовка в Twenty Seventeen? Как передать значение специального поля в короткий код? Дизайн одиночной страницы, сохранение в настройках темы Как отредактировать / заменить функцию Parent functions.php в Child Theme, чтобы добавить класс «Walker» Укажите несколько категорий для настраиваемого шаблона сообщения – FATAL ERROR Переписывание основной функциональности WordPress: изменение личных сообщений удаление контейнера списка <ul> из вывода настраиваемого меню Сложность с функцией PHP, которая отображает формат сообщения в WordPress

Как я могу реализовать поиск по местоположению (zip-код) в WordPress?

Я работаю на локальном веб-сайте каталога, который будет использовать пользовательские типы сообщений для бизнес-записей. Одним из полей будет «Почтовый индекс». Как настроить поиск по местоположению?

Я бы хотел, чтобы посетители могли ввести свой почтовый индекс и выбрать категорию и показать все предприятия с определенным радиусом или все предприятия, заказанные по расстоянию. Я видел пару плагинов, которые утверждают, что делают это, но они не поддерживают WordPress 3.0. Какие-либо предложения?

Solutions Collecting From Web of "Как я могу реализовать поиск по местоположению (zip-код) в WordPress?"

Я бы изменил ответ от gabrielk и связанного блога , используя индексы базы данных и минимизируя количество фактических вычислений расстояния .

Если вы знаете координаты пользователя и знаете максимальное расстояние (например, 10 км), вы можете нарисовать ограничивающий прямоугольник, который составляет 20 км на 20 км, с текущим расположением посередине. Получите эти ограничивающие координаты и запросите только запасы между этими широтами и долготами . Еще не используйте функции тригонометрии в запросе базы данных, так как это предотвратит использование индексов. (Таким образом, вы можете получить магазин, который находится на расстоянии 12 км от вас, если он находится в северо-восточном углу ограничительной рамки, но мы вышлем его на следующем шаге.)

Только вычислите расстояние (как птица летит или с фактическими направлениями движения, как вы предпочитаете) для нескольких возвращенных магазинов. Это значительно улучшит время обработки, если у вас будет большое количество магазинов.

Для соответствующего поиска ( «дайте десять ближайших магазинов» ) вы можете сделать аналогичный поиск, но с предварительным расстоянием (так что вы начинаете с области 10 км на 10 км, а если у вас недостаточно магазинов, вы расширяете ее до 20 км на 20 км и т. Д.). Для этой начальной оценки расстояния вы вычисляете количество магазинов по общей площади и используете это. Или запишите количество требуемых запросов и адаптируйте их с течением времени.

Я добавил полный пример кода в связанном с Майком вопросе , и вот расширение, которое дает вам самые близкие местоположения X (быстро и едва тестировалось):

class Monkeyman_Geo_ClosestX extends Monkeyman_Geo { public static $closestXStartDistanceKm = 10; public static $closestXMaxDistanceKm = 1000; // Don't search beyond this public function addAdminPages() { parent::addAdminPages(); add_management_page( 'Location closest test', 'Location closest test', 'edit_posts', __FILE__ . 'closesttest', array(&$this, 'doClosestTestPage')); } public function doClosestTestPage() { if (!array_key_exists('search', $_REQUEST)) { $default_lat = ini_get('date.default_latitude'); $default_lon = ini_get('date.default_longitude'); echo <<<EOF <form action="" method="post"> <p>Number of posts: <input size="5" name="post_count" value="10"/></p> <p>Center latitude: <input size="10" name="center_lat" value="{$default_lat}"/> <br/>Center longitude: <input size="10" name="center_lon" value="{$default_lon}"/></p> <p><input type="submit" name="search" value="Search!"/></p> </form> EOF; return; } $post_count = intval($_REQUEST['post_count']); $center_lon = floatval($_REQUEST['center_lon']); $center_lat = floatval($_REQUEST['center_lat']); var_dump(self::getClosestXPosts($center_lon, $center_lat, $post_count)); } /** * Get the closest X posts to a given location * * This might return more than X results, and never more than * self::$closestXMaxDistanceKm away (to prevent endless searching) * The results are sorted by distance * * The algorithm starts with all locations no further than * self::$closestXStartDistanceKm, and then grows this area * (by doubling the distance) until enough matches are found. * * The number of expensive calculations should be minimized. */ public static function getClosestXPosts($center_lon, $center_lat, $post_count) { $search_distance = self::$closestXStartDistanceKm; $close_posts = array(); while (count($close_posts) < $post_count && $search_distance < self::$closestXMaxDistanceKm) { list($north_lat, $east_lon, $south_lat, $west_lon) = self::getBoundingBox($center_lat, $center_lon, $search_distance); $geo_posts = self::getPostsInBoundingBox($north_lat, $east_lon, $south_lat, $west_lon); foreach ($geo_posts as $geo_post) { if (array_key_exists($geo_post->post_id, $close_posts)) { continue; } $post_lat = floatval($geo_post->lat); $post_lon = floatval($geo_post->lon); $post_distance = self::calculateDistanceKm($center_lat, $center_lon, $post_lat, $post_lon); if ($post_distance < $search_distance) { // Only include those that are in the the circle radius, not bounding box, otherwise we might miss some closer in the next step $close_posts[$geo_post->post_id] = $post_distance; } } $search_distance *= 2; } asort($close_posts); return $close_posts; } } $monkeyman_Geo_ClosestX_instace = new Monkeyman_Geo_ClosestX(); 

Сначала вам понадобится таблица, которая выглядит примерно так:

 zip_code lat lon 10001 40.77 73.98 

… для каждого почтового индекса. Вы можете расширить это, добавив поля города и штата, если вы хотите посмотреть таким образом.

Затем каждому хранилищу может быть задан почтовый индекс, а когда вам нужно рассчитать расстояние, вы можете присоединиться к таблице lat / long к данным хранилища.

Затем вы будете запрашивать эту таблицу, чтобы получить широту и долготу для почтовых индексов магазина и пользователя. Как только вы его получите, вы можете заполнить свой массив и передать его функции «получить расстояние»:

 $user_location = array( 'latitude' => 42.75, 'longitude' => 73.80, ); $output = array(); $results = $wpdb->get_results("SELECT id, zip_code, lat, lon FROM store_table"); foreach ( $results as $store ) { $store_location = array( 'zip_code' => $store->zip_code, // 10001 'latitude' => $store->lat, // 40.77 'longitude' => $store->lon, // 73.98 ); $distance = get_distance($store_location, $user_location, 'miles'); $output[$distance][$store->id] = $store_location; } ksort($output); foreach ($output as $distance => $store) { foreach ( $store as $id => $location ) { echo 'Store ' . $id . ' is ' . $distance . ' away'; } } function get_distance($store_location, $user_location, $units = 'miles') { if ( $store_location['longitude'] == $user_location['longitude'] && $store_location['latitude'] == $user_location['latitude']){ return 0; $theta = ($store_location['longitude'] - $user_location['longitude']); $distance = sin(deg2rad($store_location['latitude'])) * sin(deg2rad($user_location['latitude'])) + cos(deg2rad($store_location['latitude'])) * cos(deg2rad($user_location['latitude'])) * cos(deg2rad($theta)); $distance = acos($distance); $distance = rad2deg($distance); $distance = $distance * 60 * 1.1515; if ( 'kilometers' == $units ) { $distance = $distance * 1.609344; } return round($distance); } 

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

Документация MySQL также содержит информацию о пространственных расширениях. Как ни странно, стандартная функция distance () недоступна, но проверьте эту страницу: http://dev.mysql.com/tech-resources/articles/4.1/gis-with-mysql.html для получения подробной информации о том, как «конвертировать» два значения POINT для LINESTRING, а затем вычислить длину этого. "

Обратите внимание, что каждый поставщик может предлагать разные широты и долготы, представляющие «центроид» почтового индекса. Также стоит знать, что нет реальных определенных «пограничных» файлов почтового индекса. Каждый поставщик будет иметь свой собственный набор границ, которые примерно соответствуют конкретным спискам адресов, которые составляют почтовый индекс USPS. (Например, в некоторых «границах» вам нужно будет включать обе стороны улицы, в других – только одну.) Табличные области табличного кода (ZCTA), широко используемые поставщиками, «не точно отображают области доставки почтового индекса, и не включают все почтовые коды, используемые для доставки почты » http://www.census.gov/geo/www/cob/zt_metadata.html

У многих предприятий в центре города будет свой собственный почтовый индекс. Вам нужно как можно больше набора данных, поэтому обязательно найдите список zipcodes, который включает в себя как «точечные» почтовые индексы (обычно предприятия), так и «пограничные» почтовые индексы.

У меня есть опыт работы с данными zipcode с http://www.semaphorecorp.com/ . Даже это не было на 100% точным. Например, когда мой кампус взял новый почтовый адрес и новый почтовый индекс, почтовый индекс был неуместен. Тем не менее, это был единственный источник данных, который я обнаружил, что даже HAD новый почтовый индекс вообще, так вскоре после его создания.

У меня был рецепт в моей книге, чтобы точно узнать, как удовлетворить ваш запрос … в Drupal. Он полагался на модуль Google Maps Tools ( http://drupal.org/project/gmaps , чтобы не путать с http://drupal.org/project/gmap , также достойным модулем.) Вы можете найти полезный пример кода в этих модулях, хотя, конечно, они не будут работать из коробки в WordPress.