PHP

Как вывести метки на Яндекс.Картах из MySQL+PHP

В статье рассмотрены примеры как вывести метку на карту из БД и вывод других объектов, которые находятся рядом.

1

Структура БД

В таблице `objects` находятся записи с названиями и координатами объектов:

CREATE TABLE IF NOT EXISTS `objects` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `point` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;

INSERT INTO `objects` (`id`, `name`, `point`) VALUES
(1, 'Тверская 9', '55.75985606898725,37.61054750000002'),
(2, 'Тверская, 20', '55.766642568974845,37.60237299999997'),
(3, 'Охотный Ряд, 1 ', '55.75805306898262,37.6160005'),
(4, 'Солянка, 16 ', '55.75061056899327,37.64180899999995');
2

Получение и вывод метки

Получим запись с id = 1, эта будет главная метка красного цвета.

$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'логин', 'пароль');

// Запись с `id` = 1
$sth = $dbh->prepare("SELECT * FROM `objects` WHERE `id` = 1");
$sth->execute();
$object = $sth->fetch(PDO::FETCH_ASSOC);

И выведем полученную запись на карту:

<div id="map" style="width: 100%; height:500px"></div>

<script src="http://api-maps.yandex.ru/2.1/?lang=ru-RU" type="text/javascript"></script>
<script type="text/javascript">
ymaps.ready(init);
function init() {
    var myMap = new ymaps.Map("map", {
        center: [<?php echo $object['point']; ?>],
        zoom: 16
    }, {
        searchControlProvider: 'yandex#search'
    });

    var myCollection = new ymaps.GeoObjectCollection(); 

    // Добавим метку красного цвета.
    var myPlacemark = new ymaps.Placemark([
        <?php echo $object['point']; ?>
    ], {
        balloonContent: '<?php echo $object['name']; ?>'
    }, {
        preset: 'islands#icon',
        iconColor: '#ff0000'
    });
    myCollection.add(myPlacemark);

    myMap.geoObjects.add(myCollection);
}
</script>

В результате получится следующие:

3

Поиск и вывод соседних объектов

Найдем в БД объекты которые находятся рядом в радиусе одного километра.

В системе координат один градус равен 111 км, значит 1 км = 1 / 111 = 0,009009009009009°. 

Напишем SQL запрос который найдет все объекты у которых координаты входят в требуюмыю область.

// Запись с `id` = 1
$sth = $dbh->prepare("SELECT * FROM `objects` WHERE `id` = 1");
$sth->execute();
$object = $sth->fetch(PDO::FETCH_ASSOC);

// Объекты рядом
$area = 1 / 111;
$cord = explode(',', $object['point']);

$sth = $dbh->prepare("
    SELECT 
        * 
    FROM 
        `objects` 
    WHERE 
        `id` <> {$object['id']}
        AND SUBSTRING_INDEX(`point`, ',', 1) BETWEEN {$cord[0]} - {$area} AND {$cord[0]} + {$area} 
        AND SUBSTRING_INDEX(`point`, ',', -1) BETWEEN {$cord[1]} - {$area} AND {$cord[1]} + {$area}
    ORDER BY 
        `name`
");

$sth->execute();
$list = $sth->fetchAll(PDO::FETCH_ASSOC);

Выведем найденные метки синим цветом:

<div id="map" style="width: 100%; height:500px"></div>

<script src="http://api-maps.yandex.ru/2.1/?lang=ru-RU" type="text/javascript"></script>
<script type="text/javascript">
ymaps.ready(init);
function init() {
    var myMap = new ymaps.Map("map", {
        center: [<?php echo $object['point']; ?>],
        zoom: 16
    }, {
        searchControlProvider: 'yandex#search'
    });

    var myCollection = new ymaps.GeoObjectCollection(); 

    // Добавим метку красного цвета.
    var myPlacemark = new ymaps.Placemark([
        <?php echo $object['point']; ?>
    ], {
        balloonContent: '<?php echo $object['name']; ?>'
    }, {
        preset: 'islands#icon',
        iconColor: '#ff0000'
    });
    myCollection.add(myPlacemark);

    // Добавим найденные метки.
    <?php foreach ($list as $row): ?>
    var myPlacemark = new ymaps.Placemark([
        <?php echo $row['point']; ?>
    ], {
        balloonContent: '<?php echo $row['name']; ?>'
    }, {
        preset: 'islands#icon',
        iconColor: '#0000ff'
    });
    myCollection.add(myPlacemark);
    <?php endforeach; ?>

    myMap.geoObjects.add(myCollection);
    
    // Сделаем у карты авто масштаб чтобы были видны все метки.
    myMap.setBounds(myCollection.getBounds(),{checkZoomRange:true, zoomMargin:9});
}
</script>

Результат:

07 февраля 2018