Создание поиска по своим меткам на Яндекс.Карте с использованием PHP и MySQL

Автор: | 14.10.2010

В этой заметке я хочу рассказать Вам, как можно организовать поиск по своим данным о метках с использованием PHP и MySQL.

Я в своем примере буду использовать данные по некоторым агентствам недвижимости Нижнего Новгорода.

В начале нам необходимо в базе данных MySQL создать таблицу mymetki_ymap, для хранения данных о наших метках.

Сделать это можно используя phpMyAdmin с помощью SQL-запроса:

CREATE TABLE IF NOT EXISTS `mymetki_ymap` (
  `id` int(5) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `adress` varchar(255) NOT NULL,
  `phone` varchar(255) NOT NULL,
  `lat_map` varchar(255) NOT NULL,
  `lng_map` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

Поясню значение полей таблицы:

name — служит для хранения наименования организации;
address – здесь хранится адрес расположения организации;
phone — телефоны;
lat_map и lng_map — для хранения значений долготы и широты соответственно

Также используя phpMyAdmin заполним нашу таблицу mymetki_ymap исходными данными:

INSERT INTO `mymetki_ymap` (`id`, `name`, `adress`, `phone`, `lat_map`, `lng_map`) VALUES
(1, 'Абзац ', 'Нижний Новгород, Совнаркомовская,25', '8-915-955-98-95', '43.956211', '56.324411'),
(2, 'Абсолют-НН ', 'Нижний Новгород, пр.Кораблестроителей,26/1', '(831) 227-06-35', '43.810935', '56.363608'),
(3, 'Аверс ', 'Нижний Новгород, Рождественская,24-13', '(831) 430-06-89', '43.988047', '56.327655'),
(4, 'Какаду ', 'Нижний Новгород, ул. Гордеевская, 7, ул. Б. Печерская, 83', '(831) 220-31-17, 220-31-18, 277-26-81, 432-71-97', '43.943006', '56.326348'),
(5, 'Алые паруса ', 'Нижний Новгород, пл.Театральная,5/Пискунова,6', '(831) 419-60-63, 419-57-05', '44.000426', '56.323987'),
(6, 'Альфа недвижимость ', 'Нижний Новгород, Сергея Есенина,32', '(831) 414-55-17, 249-60-02', '43.934382', '56.334867'),
(7, 'Альфа Риэлти ', 'Нижний Новгород, Чаадаева,5-320', '(831) 274-58-51,413-20-71', '43.854378', '56.329188'),
(8, 'Берегиня+ ', 'Нижний Новгород, Адмирала Васюнина,2-212', '(831) 417-55-26,417-41-41', '44.039053', '56.296729'),
(9, 'Благовест ', 'Нижний Новгород, Берёзовская,22', '(831) 274-22-70,413-23-59', '43.881471', '56.318651'),
(10, 'Благострой ', 'Нижний Новгород, Кошелева,2', '(831) 279-50-49', '43.888873', '56.314966'),
(11, 'Большой город ', 'Нижний Новгород, Максима Горького,184', '(831) 439-12-78, 411-96-40', '44.017907', '56.318895'),
(12, 'Ваш жилой континет ', 'Нижний Новгород, Маршала Воронова,3', '(831) 413-94-11,275-49-74', '43.926647', '56.323573'),
(13, 'Гарант плюс ', 'Нижний Новгород, Лескова,18', '(831) 256-36-65,259-10-46', '43.862768', '56.235931'),
(14, 'Гарант риэлти ', 'Нижний Новгород, Варварская,32-414', '(831) 419-81-59,419-81-55', '44.012876', '56.321281'),
(15, 'Геосфера ', 'Нижний Новгород, Полтавская,14-401', '(831) 438-35-35,416-70-94', '44.025273', '56.316634'),
(16, 'Дом-52 ', 'Нижний Новгород, пр.Гагарина,110в', '(831) 278-94-66,278-94-64,413-54-25', '43.977968', '56.270621'),
(17, 'Единство ', 'Нижний Новгород, Рождественская,28а', '(831) 430-50-80,439-77-01,439-77-02', '43.986834', '56.327750'),
(18, 'Жилсервис-НН ', 'Нижний Новгород, пр.Октября,15', '(831) 295-55-83', '43.864825', '56.250272'),
(19, 'Заречье ', 'Нижний Новгород, пер.Райниса,1-3', '(831) 413-62-00,257-99-79,258-50-63', '43.917547', '56.265852'),
(20, 'ЗемСтрой ', 'Нижний Новгород, Максима Горького,151', '(831) 419-42-12,414-12-21', '44.018482', '56.318246'),
(21, 'Золотое руно ', 'Нижний Новгород, Баранова,9а', '(831) 410-82-90', '43.845691', '56.335236'),
(22, 'Золотой ключик ', 'Нижний Новгород, Родионова,191', '(831) 438-47-94,413-97-61', '44.079046', '56.303481'),
(23, 'Император ', 'Нижний Новгород, Октябрьской Революции,56', '(831) 245-01-04,240-03-81', '43.937391', '56.309893'),
(24, 'Камелот Риэлти ', 'Нижний Новгород, Красных Зорь,25-1', '(831) 272-18-88,413-51-18', '43.867394', '56.333395'),
(25, 'Квадри НН ', 'Нижний Новгород, Октябрьская,27-4', '(831) 434-03-97', '44.084634', '56.293277'),
(26, 'Квартирный вопрос ', 'Нижний Новгород, Культуры,5', '(831) 215-06-83', '43.857872', '56.349629'),
(27, 'Кворум ', 'Нижний Новгород, Мечникова,39', '(831) 276-77-40,271-68-83', '43.839286', '56.336403'),
(28, 'Континет ', 'Нижний Новгород, Переходникова,29', '(831) 253-75-55', '43.899527', '56.262632'),
(29, 'Кредо ', 'Нижний Новгород, пр.Ленина,58', '(831) 258-49-29,244-93-86', '43.922057', '56.275404'),
(30, 'Ларец ', 'Нижний Новгород, Бориса Корнилова,8', '(831) 413-09-22,417-82-92,417-73-13', '44.044344', '56.299676'),
(31, 'Лига Лайн ', 'Нижний Новгород, Зайцева,31-718', '(831) 414-29-90', '43.801377', '56.373734'),
(32, 'Титан ', 'Нижний Новгород, Долгополова,24', '(831) 414-28-75,246-52-52', '43.946850', '56.319110'),
(33, 'Титул ', 'Нижний Новгород, пр.Героев,19', '(831) 270-08-33', '43.893508', '56.318106'),
(34, 'Уют-компания ', 'Нижний Новгород, пр.Октября,8-9', '(831) 295-06-47', '43.865274', '56.246891'),
(35, 'Александр Невский ', 'Нижний Новгород, пр.Ленина,56-37', '8-920-059-59-99', '43.922263', '56.276024');

Затем организуем поиск по таблице в базе данных.

YmapsML-файл формировать будем с помощью файла creat-ymapsml-avtosal.php

Код файла:

<?php
 
header("Content-type: text/xml");
 
include("bd.php");
 
echo '<ymaps xmlns="http://maps.yandex.ru/ymaps/1.x" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maps.yandex.ru/schemas/ymaps/1.x/ymaps.xsd"> 
    <Representation xmlns="http://maps.yandex.ru/representation/1.x"> 
        <Style gml:id="agentnedv"> 
            <iconStyle> 
            <href>http://api-maps.yandex.ru/i/0.4/icons/buildings.png</href> 
                <size x="27" y="26"/> 
                <offset x="-13" y="-13"/> 
            </iconStyle> 
 
            <balloonContentStyle> 
                <template>#balloonTemplate</template> 
            </balloonContentStyle> 
        </Style> 
 
        <Template gml:id="balloonTemplate"> 
            <text><![CDATA[
			<div style="font-size:12px;"> 
                        <div style="color:#ff0303;font-weight:bold">$[name]</div>                        
                        <div>Адрес: $[metaDataProperty.AnyMetaData.adres|не задан]</div>
                        <div>Телефон: $[metaDataProperty.AnyMetaData.telefon|не задан]</div>         
                    </div>]]></text> 
        </Template> 
    </Representation> 
 
    <GeoObjectCollection> 
        <gml:name>Объекты карте</gml:name> 
        <style>#agentnedv</style> 
        <gml:featureMembers>';
 
$query1= "SELECT * FROM mymetki_ymap";
$result1 = mysql_query($query1);
while ($par1 = mysql_fetch_array($result1))
{	
 
 
echo '<GeoObject>';
echo '<gml:name>', $par1['name'], '</gml:name>';
echo '<gml:metaDataProperty>';
echo '<AnyMetaData>';
echo '<adres>', $par1['adress'], '</adres>';
echo '<telefon>', $par1['phone'], '</telefon>';
echo '</AnyMetaData>';
echo '</gml:metaDataProperty>';
echo '<gml:Point>';
echo '<gml:pos>', $par1['lat_map'], ' ', $par1['lng_map'], '</gml:pos>';
echo '</gml:Point>';
echo '</GeoObject>';
 
echo "n";
 
}
 
echo '</gml:featureMembers>
    </GeoObjectCollection>
</ymaps>';
 
 
?>

В начале мы объявляем тип файла для браузера text/xml.

Затем подключаем файл bd.php для соединения с базой данных:

<?php
 
$sdb_name = "localhost";
$user_name = "user";
$user_password = "user123";
$db_name = "ymaps_bd";
 
// соединение с сервером базы данных
if(!$link = mysql_connect($sdb_name, $user_name, $user_password))
{
  echo "<br>Не могу соединиться с сервером базы данных<br>";
  exit();
}
 
// выбираем базу данных
if(!mysql_select_db($db_name, $link))
{
  echo "<br>Не могу выбрать базу данных<br>";
  exit();
}
 
mysql_query('SET NAMES utf8');
 
?>

После с помощью оператора echo формируем YMapsML-файл.

Задаем стиль agentnedv для отображения значка метки iconStyle и шаблон содержимого балуна balloonTemplate

Выбираем данные из таблицы mymetki_ymap и формируем объекты геоколлекции.

Подробнее о формате YmapsML можно прочитать в документации

Файл vivagentnedv-ymap.html будет выводить карту с метками из файла YmapsML.

Код:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <title>Поиск по своим меткам на Яндекс.Карте с использованием PHP и MySQL</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
 <script src="http://api-maps.yandex.ru/1.1/index.xml?key=ANpUFEkBAAAAf7jmJwMAHGZHrcKNDsbEqEVjEUtCmufxQMwAAAAAAAAAAAAvVrubVT4btztbduoIgTLAeFILaQ==~AMSxmUwBAAAA5WSyQAMAwB5YJ3rvTgSgDcPJynaIsXvmUkYAAAAAAAAAAABv1IbpHjj4ZIFUHyMRhnQtZxjXZg==" type="text/javascript"></script> 
    <script language="JavaScript" type="text/javascript"> 
 
	var map;
 
        // Создание обработчика для события window.onLoad
        YMaps.jQuery(function () {
            // Создание экземпляра карты и его привязка к созданному контейнеру
            map = new YMaps.Map(YMaps.jQuery("#YMapsID")[0]);
 
            // Установка для карты ее центра и масштаба
            map.setCenter(new YMaps.GeoPoint(43.998779,56.316537), 12);
 
			map.addControl(new YMaps.Zoom());
	        map.addControl(new YMaps.TypeControl());
	        map.addControl(new YMaps.ToolBar());
 
            // Создание и добавление YMapsML-документа на карту
            var ml = new YMaps.YMapsML("http://map.cek.ru/files/fs/creat-ymapsml-agentnedv.php");
            map.addOverlay(ml);
 
            // Обработчик неудачной загрузки YMapsML
            YMaps.Events.observe(ml, ml.Events.Fault, function (ml, error) {
                alert('Ошибка: ' + error);
            });
        });
 
</head>
<body>
 
<table> 
    <tr> 
        <td style="vertical-align:top; "> 
    <div id="YMapsID" style="width:500px;height:400px"></div> 
</td> 
<td style="vertical-align:top; "> 
<strong>Поиск поставщиков агенств недвижимости по карте:</strong> 
<form action="#" method="POST" onSubmit="do_search(this.company.value); return false;">  
<input type="text" id="company" name="company" size="30" value="" /><br> 
<em>например: Абзац</em> 
<p><input type="submit" value="Найти" /></p></form> 
<div id="search_res"></div> 
</td> 
</tr> 
 
</table></p> 
 
</body>
</html>

В разделе body расположена таблица в одной ячейке отображается карта , в другой форма поиска с контейнером для результатов.

Замечание: если Вы будете выполнять пример на локальном компьютере нужно чтобы creat-ymapsml-agentnedv.php был доступен из Интернета, т. к. содержимое файла YmapsML обрабатывается сервером Яндекса.

Для осуществления поиска мы добавим в код файла vivagentnedv-ymap.html функцию do_search.

Код функции:

function do_search(company){
map.removeAllOverlays();
YMaps.jQuery('#search_res').html('');
 
YMaps.jQuery.getJSON("http://map.cek.my/files/fs/searcheagentnedv.php", {company:company}, function(json){
 
if (json.status == 'OK') {  
var src_res="<p><strong>результаты поиска: </strong></p>";
src_res=src_res+'<p><strong>Найдено объектов: '+json.markers.length+'</strong></p>';
for (i = 0; i < json.markers.length; i++) {
var placemark=new YMaps.Placemark(new YMaps.GeoPoint(json.markers[i].lat,json.markers[i].lon));
placemark.description='<div style="color:#ff0303;font-weight:bold">'+json.markers[i].cname+'</div>';
placemark.description=placemark.description+'<strong>Адрес:</strong> '+json.markers[i].address+'<br><strong>Телефон:</strong> '+json.markers[i].phone;
map.addOverlay(placemark);
src_res=src_res+'<p><a href="#" onClick="return go_to('+json.markers[i].lat+', '+json.markers[i].lon+",'"+json.markers[i].cname+"','"+json.markers[i].address+"','"+json.markers[i].phone+"','"+json.markers[i].id+"');"+'">'+json.markers[i].cname+'</a><br>'+json.markers[i].address+'</p>';
}
 
}
else
{
var src_res = '<p><strong>результаты поиска</strong></p><font color="red">По Вашему запросу объектов на карте не найдено</font>';
}
YMaps.jQuery('#search_res').html(src_res);
 
});
}

В качестве параметра функции выступает company — название компании из формы поиска.

В функции do_search в начале мы удаляем все оверлеи с карты с помощью
map.removeAllOverlays() и очищаем контейнер с результатами поиска Ymaps.jQuery(‘#search_res’).html(‘ ‘);
После мы осуществляем AJAX запрос к файлу searcheagentnedv.php используя функцию getJSON с
помощью встроенной в API Яндекс.Карт JavaScript-библиотеки jQuery.

В файле searcheagentnedv.php мы осуществляем запрос к базе данных для поиска и формируем файл формата JSON с результатами поиска.

Подробнее о формате JSON можно прочитать здесь

В месте с данными о найденных метках передается параметр успешности поиска status, если он равен OK, то мы обрабатываем переданные значения — наносим найденные метки на карту и выводим список со ссылками в контейнер результатов поиска search_res.

Если поиск завершился неудачно, выводится сообщение: «По Вашему запросу объектов на карте не найдено».

По клику по названию метки в списке результатов поиска вызывается функция go_to — происходит центрирование карты по координатам данной метки и открывается балун с информацией.

Код функции:

function go_to(lat,lon,cname,address,phone,id){
map.setCenter(new YMaps.GeoPoint(lat,lon),17);
map.removeAllOverlays();
var placemark=new YMaps.Placemark(new YMaps.GeoPoint(lat,lon));
placemark.name='<div style="color:#ff0303;font-weight:bold">'+cname+'</div>';
placemark.description='<div><strong>Адрес:</strong> '+address+'<br><strong>Телефон:</strong> '+phone+'</div>';
map.addOverlay(placemark);
placemark.openBalloon();
return false;
}

Теперь приведу код файла searcheagentnedv.php, который осуществляет запрос к базе данных и формирует результаты поиска в формате JSON:

Код

<?php
 
include("bd.php");
 
header('Content-Type: text/html; charset=utf-8');
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
 
$company = $_GET['company'];
 
$name_remont = htmlspecialchars(trim($company));
 
$json = '{markers:['."n";
 
$query1= "SELECT * FROM mymetki_ymap where  name LIKE '%$name_remont%'  ORDER BY name";
$result1 = mysql_query($query1);
 
if(mysql_num_rows($result1)>0)
{
while ($par1 = mysql_fetch_array($result1)){
 
$cname =  htmlspecialchars($par1['name']);
 
$json.= "n".'{'.'"id": "'.$par1['id'].'",';
 
$json.= '"cname": "'.$cname.'",';
 
$json.= '"address": "'.$par1['adress'].'",';
 
$json.= '"phone": "'.$par1['phone'].'",';
 
$json.= '"lat": "'.$par1['lat_map'].'",';
 
$json.=  '"lon": "'.$par1['lng_map'].'"';
 
$json.= '},';
 
}
 
$json = substr($json, 0,-1);
 
echo  $json;
 
echo '], ', "n",  '"status": "OK"', "n", '}';
 
}
else
{
echo '{"status": "false"}';
}
 
}
 
?>

Вид JSON-файла с результатами поиска (запрос: альфа):

{markers:[

{"id": "6","cname": "Альфа недвижимость ","address": "Нижний Новгород, Сергея Есенина,32","phone": "(831) 414-55-17, 249-60-02","lat": "43.934382","lon": "56.334867"},
{"id": "7","cname": "Альфа Риэлти ","address": "Нижний Новгород, Чаадаева,5-320","phone": "(831) 274-58-51,413-20-71","lat": "43.854378","lon": "56.329188"}],
"status": "OK"
}

В коде файла searcheagentnedv.php все предельно ясно.

Проверяем как отправлено значение переменной company, если через AJAX, то $_SERVER[‘HTTP_X_REQUESTED_WITH’] == ‘XMLHttpRequest’.

Мы получаем переданные методом GET данные, удаляем из строки $company лишние пробелы и производим преобразование спецсимволов в их HTML эквиваленты, на всякий случий, если кто-то захочет в нашу форму написать какой-либо код.

Затем мы посылаем запрос к таблице mymetki_ymap и если результат найден с помощью оператора echo формируем содержимое JSON-файла.

Если результат не найден, отправляем строку {"status": "false"}.

Посмотреть работу примера в действии

Загрузить исходные файлы примера

Создание поиска по своим меткам на Яндекс.Карте с использованием PHP и MySQL: 3 комментария

  1. Саша

    У YMaps.SearchControl (http://api.yandex.ru/maps/jsapi/doc/ref/reference/searchcontrol.xml) можно указать опции геокодирования. Одна из них, позволяет переопределить используемый сервис геокодирования — geocodeProvider. Для этого нужно реализовать несложный интерфейс YMaps.IGeocodeProvider (http://api.yandex.ru/maps/jsapi/doc/ref/reference/igeocodeprovider.xml).

    Таким образом, вы можете «научить» SearchControl искать по своей базе объектов, а если в базе ничего не было найдено, то пробовать произвести обычное геокодирование.

    Думаю, что это будет неплохим продолжением вашей статьи.

  2. Юрий

    Большое спасибо авторам за объемную работу по кластерам, очень полезные скрипты, а самое главное работают без отказно!!! РЕСПЕКТ!

  3. Олег

    Подскажите пож-та, после обработки поиска можно ли выводить данные с различными иконками? например иконка кафе и кинотеатра.

    можете помочь с примером? эти данные надо добавлять в вывод
    JSON-файла??

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *