В одном проекте, с которым пришлось столкнуться по долгу службы, клиент решил немного упростить жизнь гастарбайтеров-курьеров, которые занимаются доставкой товаров из интернет-магазина по Москве. Чтобы ребятам, плохо ориентирующимся в карте столицы, было проще и быстрее добираться до адресата, в путевом листе, помимо адреса, решили указывать ближайшую станцию метро. По задумке клиента, данное нововведение должно повысить скорость доставки и снизить процент потерявшихся курьеров на московских изогнутых улицах.
Путевой лист должен формироваться на сервере – это и стало основной проблемой. Раньше работать с адресами и прочими элементы карты, приходилось только на клиентской стороне. То есть все возможные манипуляции с объектами карты осуществлялись с помощью 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, подробнее можно почитать тут.
Спасибо за готовые решения типовых задач.
#тоже самое по гугл
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;
}