Сфера тегов

Организуем поиск в заданном радиусе от почтового индекса

Есть следующая задача: необходимо организовать поиск почтовых индексов, расположенных в заданном радиусе (км или мили) от заданного индекса. Я буду описывать как это можно реализовать на PHP.

Для решения этой задачи нам потребуется база данных с долготой/широтой каждого индекса для той страны, в которой мы хотим осуществлять поиск. Базу можно скачать бесплатно на http://download.geonames.org/export/zip/. Итак, теперь нам надо поместить эту базу данных MySQL. Для этого создаем таблицу, создаем таблицу, выполняя SQL запрос:

CREATE TABLE `zip_code` (
  `id` int(11) unsigned NOT NULL auto_increment,
  `zip_code` varchar(20) collate utf8_bin NOT NULL,
  `city` varchar(180) collate utf8_bin default NULL,
  `county` varchar(50) collate utf8_bin default NULL,
  `state_name` varchar(50) collate utf8_bin default NULL,
  `state_prefix` varchar(2) collate utf8_bin default NULL,
  `area_code` varchar(3) collate utf8_bin default NULL,
  `time_zone` varchar(50) collate utf8_bin default NULL,
  `lat` float NOT NULL,
  `lon` float NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `zip_code` (`zip_code`)
)

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

$file = file("DE.TXT");
$fp = fopen("db.sql", "w");

for ($i=0;$i<sizeof($file);$i++)
{
  $s=explode("\t",$file[$i]);
  $ss[]="'".$s[1]."'";
  $ss[]="'".$s[2]."'";
  $ss[]="'".$s[5]."'";
  $ss[]="'".$s[3]."'";
  $ss[]="'".$s[4]."'";
  $ss[]="'".$s[8]."'";
  $ss[]="'CET'"; //укажите нужный часовой пояс
  $ss[]=$s[9];
  $ss[]=$s[10];
  $ii=$i+1;
  fputs($fp,"INSERT INTO `zip_code` VALUES ($ii, ".implode(",",$ss).");\n");
  unset($ss);
}
fclose($fp);

Далее будем использовать скрипт Micah Carrick "Zipcode PHP class" для организации поиска. Рассмотрим его подробнее.
Итак, подключаем класс к нашему проекту и создаем объект:

require_once('zipcode.class.php');
$z = new zipcode_class;

Какие фукнции он может выполнять:

1. Получение расстояния между заданными индексами

$miles = $z->get_distance(97214, 98501);

Кстати, в самом файле класса zipcode.class.php можно переключать единицы измерения. Для этого находим строку

var $units = _UNIT_MILES;        // miles or kilometers

и заменяем ее на

var $units = _UNIT_KILOMETERS;        // miles or kilometers

2. Получение всех почтовых индексов, лежащих в заданном радиусе от заданного индекса.

$zips = $z->get_zips_in_range('97214', 2, _ZIPS_SORT_BY_DISTANCE_ASC, true);

В качестве параметров сортировки могут быть следующие:
_ZIPS_SORT_BY_DISTANCE_ASC - сортировка по возрастанию по расстояниям
_ZIPS_SORT_BY_DISTANCE_DESC - сортировка по убыванию по расстояниям
_ZIPS_SORT_BY_ZIP_ASC - сортировка по возрастанию по почтовым индексам
_ZIPS_SORT_BY_ZIP_DESC - сортировка по убыванию по почтовым индексам

Затем вывести полученные результаты можно к примеру так:

if ($zips === false) echo 'Error: '.$z->last_error; // выводим ошибку
else {
  
   foreach ($zips as $key => $value) {
      echo "Почтовый индекс <b>$key</b> на расстоянии <b>$value</b> км от <b>97214</b>.<br />";
   }
  
   echo "<br /><i>get_zips_in_range() выполнен за <b>".$z->last_time."</b> секунд.</i><br />";
}

3. Получение описания о заданном индексе

$details = $z->get_zip_details('97214');

if ($details === false) echo 'Error: '.$z->last_error;
else {
   foreach ($details as $key => $value) {
      $key = str_replace('_',' ',$key);
      $key = ucwords($key);
      echo "$key:&nbsp;$value<br />";
   } 
}

На этом всё, спасибо за внимание!

Оставить комментарий