В одном проекте, с которым пришлось столкнуться по долгу службы, клиент решил немного упростить жизнь гастарбайтеров-курьеров, которые занимаются доставкой товаров из интернет-магазина по Москве. Чтобы ребятам, плохо ориентирующимся в карте столицы, было проще и быстрее добираться до адресата, в путевом листе, помимо адреса, решили указывать ближайшую станцию метро. По задумке клиента, данное нововведение должно повысить скорость доставки и снизить процент потерявшихся курьеров на московских изогнутых улицах.
Путевой лист должен формироваться на сервере – это и стало основной проблемой. Раньше работать с адресами и прочими элементы карты, приходилось только на клиентской стороне. То есть все возможные манипуляции с объектами карты осуществлялись с помощью js и как реализовать подобный функционал на сервере не понятно.
Яндекс карты и http-запросы
Все оказалось предельно просто. У яндекса есть замечательный сервис «геокодирование» от яндекс карт, который позволяет делать http-запросы к своим api. Сервис позволяет определять координаты и получать информацию об объектах расположенных на яндекс картах. Подробнее можно почитать тут: документация. Данных, предоставляемых яндексом, вполне достаточно, чтобы решить задачку, подкинутую клиентом.
Получение координат адреса с помощью php
Api яндекса позволяют получать данные как в формате xml, так и json. Работать с json-он мне удобнее, поэтому в примерах используется именно он.
Чтобы получить ближайшую станцию метро, необходимо передать в api координаты точки на карте. Координаты должны быть в формате «долгота, широта». Но в базе данных с заказами нет такой информации, есть только адрес. Поэтому необходимо сделать предварительный запрос и получить координаты точки по определенному адресу. Сделать это можно вот так:
/**
* Получение координат адреса
*
* @param $address string - адрес точки
* @return bool | array - false или массив с координатами [долгота, широта]
*/
function getCoordNameByAddress($address){
// удаление лишних пробелов между словами
$address = preg_replace("/ {2,}/", " ", $address);
// замена пробелов на плюсы
$address = str_replace(" ", "+", $address);
// формируется урл для запроса
$url_get_coord = "https://geocode-maps.yandex.ru/1.x/?geocode={$address}&format=json&results=1";
$result = @file_get_contents($url_get_coord);
// если произошла ошибка при отправке запроса или ответе сервера
if(!$result) return false;
$result = json_decode($result);
// если ни чего не нашлось
if(count($result->response->GeoObjectCollection->featureMember) == 0) return false;
// получение координат точки
$coord = $result->response->GeoObjectCollection->featureMember[0]->GeoObject->Point->pos;
return explode(" ", $coord);
}
Получение ближайшей станции метро с помощью php
Теперь, имея координаты адресата, можно получить адрес и название ближайшего метро. В примере ниже, показано определение только названия станции. Но у вас не составит ни какого труда получить и другую информацию о метро, достаточно только вытащить нужные значения из массива данных, который отдает api. Также в запросе можно изменить или вовсе не использовать параметр «results», который определяет количество найденных объектов. Мне было нужно найти только одну станцию, поэтому в примере results равен 1.
/**
* Получение ближайшего метро по координатам
*
* @param array - массив с координатами [долгота, широта]
* @return bool | string - false или название ближайшего метро
*/
function getMetroNameByCoord($coord){
$coord_str = implode(",", $coord);
$url_get_metro = "https://geocode-maps.yandex.ru/1.x/?geocode={$coord_str}&kind=metro&format=json&results=1";
$result = @file_get_contents($url_get_metro);
// если произошла ошибка при отправке запроса или ответе сервера
if(!$result) return false;
$result = json_decode($result);
// если ни чего не нашлось
if(count($result->response->GeoObjectCollection->featureMember) == 0) return false;
return $result->response->GeoObjectCollection->featureMember[0]->GeoObject->name;
}
Поиск ближайшей станции метро по адресу с помощью php
И остается только привести пример использования двух, описанных выше, функций. Возьмем для примера адрес «Петровки 38» и найдем ближайшую к ней станцию метро. Возможно кому-нибудь, спешно покидающему здание МВД, пригодится эта информация.
// адрес $address = "Петровка улица, 38, Москва"; // получение координат адреса $coord = getCoordNameByAddress($address); // получение ближайшего метро по координатам $metro = getMetroNameByCoord($coord); // вывод результата var_dump($metro);
Послесловие
Яндекс установил лимит на количество обращений к своему сервису, он составляет 25 тысяч запросов в сутки. Это большой запас и его будет достаточно для многих сайтов или сервисов. Но если этого количества вам будет не достаточно, то всегда можно воспользоваться платной версией api, подробнее можно почитать тут.

(8 оценок, среднее: 4,50 из 5)
Спасибо за готовые решения типовых задач.
#тоже самое по гугл
function getCoordinatesByAddress($address){global $log;
$log->LogDebug("Called '".(__FUNCTION__)."' function with params: ".implode(',',func_get_args()));
if (!is_string($address))die("All Addresses must be passed as a string");
$_url = sprintf('http://maps.google.com/maps?output=js&q=%s',rawurlencode($address));
$_result = false;
if($_result = file_get_contents($_url)) {
if(strpos($_result,'errortips') > 1 || strpos($_result,'Did you mean:') !== false) return false;
preg_match('!center:\s*{lat:\s*(-?\d+\.\d+),lng:\s*(-?\d+\.\d+)}!U', $_result, $_match);
$_coords['lat'] = $_match[1];
$_coords['long'] = $_match[2];
}
return $_coords;
}