Организация вывода данных на карту Google Maps,  используя PHP и MySQL

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

В этой я расскажу, как можно осуществить вывод введенных данных на карту Google.

Сделать это можно различными способами.

Первый, наиболее простой – это просто добавления данных о метках в файл php создания карты Google.

Второй – это формирование XML-файла с данными, с которым будет взаимодействовать карта с помощью асинхронных JavaScript-запросов.

И третий – формирование KML-файла и отображение его на карте.

В этой заметке я рассмотрю второй способ – использование XML-файла с данными.

А в продолжении я подробно разберу третий.

Но в начале несколько слов о первом способе и почему я его не рекомендую использовать.

В первом способе код для отображения карты помещается в файл с расширением php.

А затем мы подключаемся к базе данных и формируем средствами PHP JavaScript-код для вывода каждого маркера в отдельности.

Этот способ хорош, если у Вас мало маркеров, приблизительно около 10.

Но когда количество меток велико это замедляет первоначальную загрузку страницы с картой, кроме этого усложняется процесс отладки приложения.

По этому, я его не рассматриваю подробно, к тому же его не сложно реализовать самому взяв за основу пример вывода маркера на карту Google.

И так вступление закончено, переходим к главной части.

Рассмотрим второй способ — формирование XML-файла с данными с последующем выводом маркеров на карту Google Maps.

В начале, мы должны получить  XML-файл с параметрами маркеров из базы данных MySQL.

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

XML-файл можно сформировать тремя различными способами, все зависит от возможностей Вашего хостинга и версии PHP на нем установленной.

Самый простой – использовать оператор echo.

Привожу код файла:

 
<?php
require("phpsqlinfo_dbinfo.php");
 
function parseToXML($htmlStr) 
{ 
$xmlStr=str_replace('<','&lt;',$htmlStr); 
$xmlStr=str_replace('>','&gt;',$xmlStr); 
$xmlStr=str_replace('"','&quot;',$xmlStr); 
$xmlStr=str_replace("'",'&#39;',$xmlStr); 
$xmlStr=str_replace("&",'&amp;',$xmlStr); 
return $xmlStr; 
} 
 
// Выбираем данные о маркерах из таблицы
$query = "SELECT * FROM markers WHERE 1";
$result = mysql_query($query);
if (!$result) {
  die('Invalid query: ' . mysql_error());
}
 
header("Content-type: text/xml");
 
// Начало XML-файла, вывод с помощью echo
echo '<markers>';
 
// Повторяем вывод для каждой записи
while ($row = @mysql_fetch_assoc($result)){
  // ADD TO XML DOCUMENT NODE
  echo '<marker ';
  echo 'name="' . parseToXML($row['name']) . '" ';
  echo 'address="' . parseToXML($row['address']) . '" ';
  echo 'lat="' . $row['lat'] . '" ';
  echo 'lng="' . $row['lng'] . '" ';
  echo 'type="' . $row['type'] . '" ';
  echo '/>';
}
 
//Конец XML-файла
echo '</markers>';
 
?>

Производим подключение к базе данных в файле phpsqlinfo_dbinfo.php

После мы используем функцию parseToXML для декодирования специальных символов  (>,<,’,”), чтобы не возникало ошибок XML.

Потом мы выбираем данные о маркерах из таблицы markers.

Строкой header("Content-type: text/xml"); мы сообщаем браузеру тип формируемого файла.

А затем выводим содержимое в  виде XML-кода.

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

Второй способ вывода – использование dom_xml-функций.

В начале Вы должны проверить конфигурацию PHP или попытаться использовать функцию domxml_new_doc() для проверки возможности использовать dom_xml-функции.

Если Вы имеете доступ к dom_xml-функциям, то Вы можете использовать их для создания XML-узлов и вывода XML-документа на экран. С помощью функций dom_xml Вы можете создавать XML-документы практически любой сложности.

В PHP, для начала, нужно инициализировать новый XML-документ и создать родительский узел “marlers”. Затем нужно подключиться к БД и произвести выбор необходимых данных при помощи запроса вида SELECT * (выбрать все) к таблице с именем “markers” и пройтись по всем результатам этой выборки. Для каждой записи в таблице (каждого заведения) будет создаваться свой узел в XML-документе, атрибуты которого будут полями из соответствующей записи таблицы, — этот узел будет присоединяться к родительскому узлу. После этого Вы получите готовый XML-документ.

Еще одно важное замечание, если Вы используете кодировку своих данных отличную от UTF-8 с начала нужно перекодировать Ваши данные в эту кодировку (UTF-8).

Приводу код примера:

 
<?php
require("phpsqlinfo_dbinfo.php");
 
// Start XML file, create parent node
$doc = domxml_new_doc("1.0");
$node = $doc->create_element("markers");
$parnode = $doc->append_child($node);
 
// Select all the rows in the markers table
$query = "SELECT * FROM markers WHERE 1";
$result = mysql_query($query);
if (!$result) {
  die('Invalid query: ' . mysql_error());
}
 
header("Content-type: text/xml");
 
// Iterate through the rows, adding XML nodes for each
while ($row = @mysql_fetch_assoc($result)){
  // ADD TO XML DOCUMENT NODE
  $node = $doc->create_element("marker");
  $newnode = $parnode->append_child($node);
 
  $newnode->set_attribute("name", $row['name']);
  $newnode->set_attribute("address", $row['address']);
  $newnode->set_attribute("lat", $row['lat']);
  $newnode->set_attribute("lng", $row['lng']);
  $newnode->set_attribute("type", $row['type']);
}
 
$xmlfile = $doc->dump_mem();
echo $xmlfile;
 
?>

И третий способ – это использование DOM-функций PHP версии 5.

С начала, необходимо убедиться в том, что Вы используете PHP версии 5. Если Ваша версия PHP ниже, то используйте какой-либо из предыдущих способов.

В PHP нужно инициализировать новый XML-документ и создать родительский узел “markers”. Затем нужно подключиться к БД и произвести выбор необходимых данных при помощи запроса вида SELECT * (выбрать все) к таблице с именем “markers” и пройтись по всем результатам этой выборки. Для каждой записи в таблице (каждого заведения) будет создаваться свой узел в XML-документе, атрибуты которого будут полями из соответствующей записи таблицы, — этот узел будет присоединяться к родительскому узлу. После этого Вы получите готовый XML-документ.

Приводу готовый код примера:

 
<?php  
 
require("phpsqlinfo_dbinfo.php");
 
// Start XML file, create parent node
 
$dom = new DOMDocument("1.0");
$node = $dom->createElement("markers");
$parnode = $dom->appendChild($node); 
 
// Select all the rows in the markers table
 
$query = "SELECT * FROM markers WHERE 1";
$result = mysql_query($query);
if (!$result) {  
  die('Invalid query: ' . mysql_error());
} 
 
header("Content-type: text/xml"); 
 
// Iterate through the rows, adding XML nodes for each
 
while ($row = @mysql_fetch_assoc($result)){  
  // ADD TO XML DOCUMENT NODE  
  $node = $dom->createElement("marker");  
  $newnode = $parnode->appendChild($node);   
  $newnode->setAttribute("name",$row['name']);
  $newnode->setAttribute("address", $row['address']);  
  $newnode->setAttribute("lat", $row['lat']);  
  $newnode->setAttribute("lng", $row['lng']);  
  $newnode->setAttribute("type", $row['type']);
} 
 
echo $dom->saveXML();
 
?>

После того как Вы получили XML-файл с данными необходимо создать карту , используя JavaScript и подгрузить его на нее.

Для того, чтобы загрузить XML-файл на страницу, необходимо использовать API-функцию GDownloadURL. GDownloadURL является как бы оболочкой для метода XMLHttpRequest, который используется для отправки запросов в XML-форме. Первым параметром функции GDownloadURL является путь к XML-файлу. Второй же параметр – это функция, которая будет выполняться при получении ответа от XML.
Примечание: очень важно понять, что GDownloadURL работает асинхронно – функция, являющаяся вторым параметром GDownloadURL, не будет срабатывать, как только Вы применили этот метод. Чем объемней Ваш XML-файл, тем больше потребуется времени для вызова этой функции-параметра. Не следует помещать никакого кода, отвечающего за размещение маркеров на карте, после метода GDownloadURL – его нужно помещать в функцию-параметр.

Функция-параметр необходима для того, чтобы отыскать все элементы “markers” в XML. Для каждого маркера мы восстанавливаем значения названия, адреса, типа и координат, а затем мы передаем эти значения функции creatMarker, которая помещает маркеры на карту.

 
GDownloadUrl("phpsqlajax_genxml2.php", function(data) {
          var xml = GXml.parse(data);
          var markers = xml.documentElement.getElementsByTagName("marker");
          for (var i = 0; i < markers.length; i++) {
            var name = markers[i].getAttribute("name");
            var address = markers[i].getAttribute("address");
            var type = markers[i].getAttribute("type");
            var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
                                    parseFloat(markers[i].getAttribute("lng")));
            var marker = createMarker(point, name, address, type);
            map.addOverlay(marker);
          }
        });

Создаем иконки для маркеров

Вы можете использовать класс GIcon для определения произвольных изображений, которые будут отображаться в качестве маркера. Для начала определим три объекта: iconGreen, iconBlue и iconRed.

Предупреждение: Вы можете и не определять столько свойств, сколько показано в примере, но, делая так, Вы рискуете столкнуться с различными ошибками позже.

Также можно создать ассоциативный массив, который будет связывать каждый объект GIcon с определенным типом заведения: кафе, рестораном или баром. Такой подход поможет Вам в дальнейшем легко разбираться с маркерами, созданными с использованием данных из внешнего XML-файла.

 
var iconBlue = new GIcon(); 
    iconBlue.image = 'http://labs.google.com/ridefinder/images/mm_20_blue.png';
    iconBlue.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
    iconBlue.iconSize = new GSize(12, 20);
    iconBlue.shadowSize = new GSize(22, 20);
    iconBlue.iconAnchor = new GPoint(6, 20);
    iconBlue.infoWindowAnchor = new GPoint(5, 1);
 
    var iconRed = new GIcon(); 
    iconRed.image = 'http://labs.google.com/ridefinder/images/mm_20_red.png';
    iconRed.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
    iconRed.iconSize = new GSize(12, 20);
    iconRed.shadowSize = new GSize(22, 20);
    iconRed.iconAnchor = new GPoint(6, 20);
    iconRed.infoWindowAnchor = new GPoint(5, 1);
 
    var iconGreen = new GIcon(); 
    iconGreen.image = 'http://labs.google.com/ridefinder/images/mm_20_green.png';
    iconGreen.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
    iconGreen.iconSize = new GSize(12, 20);
    iconGreen.shadowSize = new GSize(22, 20);
    iconGreen.iconAnchor = new GPoint(6, 20);
    iconGreen.infoWindowAnchor = new GPoint(5, 1)
 
    var customIcons = [];
    customIcons["restaurant"] = iconBlue;
    customIcons["bar"] = iconRed;
    customIcons["cafe"] = iconGreen;

После этого мы создаем маркеры и информационные окна.

Вы должны поместить весь код, который необходим для создания маркеров в функцию createMarker. Так как массив customIcons был определен глобально, то мы без помех можем передавать его элементы конструктору класса GMarker. Затем нужно написать HTML-код, который будет отображаться в инфо-окне.

Подсказка: некоторые уроки советуют Вам хранить информацию, отформатированную в виде HTML. Но это не есть хорошо, так как Вы не можете свободно манипулировать HTML-форматированием.

После написания отображаемого HTML-кода нужно добавить события для маркеров, чтобы при щелчке по маркеру появлялось инфо-окно.

 
function createMarker(point, name, address, type) {
      var marker = new GMarker(point, customIcons[type]);
      var html = "<b>" + name + "</b> <br/>" + address;
      GEvent.addListener(marker, 'click', function() {
        marker.openInfoWindowHtml(html);
      });
      return marker;
    }

Ниже приведен код, который связывает все, что мы написали выше, в единое целое. Как только страница загружается – срабатывает функция загрузки карты load. Эта функция отображает карту, а затем вызывает метод GDownloadUrl. Удостоверьтесь, что функция GDownloadUrl правильно выполняет свою работу и XML-файл отображается в браузере корректно.

Полный код для вывода карты:

 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Пример вывод данных из базы на карту Google, используя XML</title>
    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAACHCJdlgAEGcD_flKUFEmVhT2yXp_ZAY8_ufC3CFXhHIE1NvwkxTeukKcKHF3ezmjTB0q6gzSBmoIUQ"
            type="text/javascript"></script>
 
    <script type="text/javascript">
    //<![CDATA[
 
    var iconBlue = new GIcon(); 
    iconBlue.image = 'http://labs.google.com/ridefinder/images/mm_20_blue.png';
    iconBlue.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
    iconBlue.iconSize = new GSize(12, 20);
    iconBlue.shadowSize = new GSize(22, 20);
    iconBlue.iconAnchor = new GPoint(6, 20);
    iconBlue.infoWindowAnchor = new GPoint(5, 1);
 
    var iconRed = new GIcon(); 
    iconRed.image = 'http://labs.google.com/ridefinder/images/mm_20_red.png';
    iconRed.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
    iconRed.iconSize = new GSize(12, 20);
    iconRed.shadowSize = new GSize(22, 20);
    iconRed.iconAnchor = new GPoint(6, 20);
    iconRed.infoWindowAnchor = new GPoint(5, 1);
 
    var iconGreen = new GIcon(); 
    iconGreen.image = 'http://labs.google.com/ridefinder/images/mm_20_green.png';
    iconGreen.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
    iconGreen.iconSize = new GSize(12, 20);
    iconGreen.shadowSize = new GSize(22, 20);
    iconGreen.iconAnchor = new GPoint(6, 20);
    iconGreen.infoWindowAnchor = new GPoint(5, 1)
 
    var customIcons = [];
    customIcons["restaurant"] = iconBlue;
    customIcons["bar"] = iconRed;
    customIcons["cafe"] = iconGreen;
 
    function load() {
      if (GBrowserIsCompatible()) {
        var map = new GMap2(document.getElementById("map"));
        map.addControl(new GSmallMapControl());
        map.addControl(new GMapTypeControl());
        map.setCenter(new GLatLng(56.32811,44.0), 13);
 
        GDownloadUrl("phpsqlajax_genxml2.php", function(data) {
          var xml = GXml.parse(data);
          var markers = xml.documentElement.getElementsByTagName("marker");
          for (var i = 0; i < markers.length; i++) {
            var name = markers[i].getAttribute("name");
            var address = markers[i].getAttribute("address");
            var type = markers[i].getAttribute("type");
            var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
                                    parseFloat(markers[i].getAttribute("lng")));
            var marker = createMarker(point, name, address, type);
            map.addOverlay(marker);
          }
        });
      }
    }
 
    function createMarker(point, name, address, type) {
      var marker = new GMarker(point, customIcons[type]);
      var html = "<b>" + name + "</b> <br/>" + address;
      GEvent.addListener(marker, 'click', function() {
        marker.openInfoWindowHtml(html);
      });
      return marker;
    }
    //]]>
  </script>
 
  </head>
 
  <body onload="load()" onunload="GUnload()">
    <div id="map" style="width: 800px; height: 600px"></div>
  </body>
</html>

Посмотреть пример в действии можно здесь.

Для написания данной заметки использовались следующие источники:

Using PHP/MySQL with Google Maps

ИСПОЛЬЗОВАНИЕ СВЯЗКИ ИЗ PHP и MySQL СОВМЕСТНО C GOOGLE MAPS

Продолжение следует …

  • Гость: Просветите непросвещенного, как вывести в InfoWindow: 1) ссылку ( при перемещении данных в базу и обратно ссылка превращается в просто текст) 2) Картинку (насколько я понимаю хранить саму картинку лучше на сервере, а в базу заносить только ссылку на ее местонахождение) помогите плиз.
  • Гость: Написал специальную заметку по этому поводу http://webmap-blog.ru/?p=518
  • Гость: Как можно вывести метки на карту не зная широты и долготы, а зная только адрес метки?
  • Гость: В Opera , Chrome , FF точки выводяться а в IE нет , в чем может быть ошибка ?
  • Гость: В строке, где прописываете ключ попробуйте строго указать кодировку Charset="utf-8"... У меня тоже вопрос к аудитории и автору. Как сделать, чтобы маркеры выводились по типам заведений...ведь если заведений будет много, будут проблемы с работой скрипта...Поэтому целесообразнее было бы выводить маркеры, только определенного типа, а слева, чтобы была форма с чекбоксами для выбора типов заведений...Нашел ссылку: http://blog.aaa-nan.info/2010/06/jquery-google-maps-api-3.html , но там для АПИ версии 3...да и в Яваскрипт я не силен
  • Гость: Хотя в статье на которую Вы ссылаетесь написано, что используется АПИ версии 3, на самом деле в примере используется 2-я версия. Это видно по строке google.load("maps", "2.x"); Я постараюсь написать специальную заметку по этой теме, применительно к данному примеру
  • Гость: Скажите, а как выводить карту для каждого ресторана отдельно? У меня база: id, name, addres, descrition и тд. Использую реврайт, то есть при клике на ресторан, выводится подробное его описание. Хочется чтобы карта выводилась в описании ресторана, и чтоб координаты брались из базы по айди-шнику ресторана.
  • Гость: Отдельно можно вывести карту для каждого ресторана делая SQL-запрос по ID к базе данных, а в коде страницы на карте выводить только выбранный объект.
  • Гость: скажи, а можно сделать вывод информации в отдельные формы, а не через маркер?
  • Гость: Не понял о каких формах идет речь
  • Гость: Спасибо за информацию, оказалось очень полезной. И особенно порадовал один из маркеров, при нажатии на который выскочил балун с известным русским словом ))
  • Гость: админ ты не мог бы подсказать как запарсить в xml мои текстовые поля вывода селекта базы тут http://ribalka02.ru/component/option,com_php/Itemid,90/ чтобы в ссылки превратились и на карту сразу вели-код скину если что, либо как тут выдавать сразу всё а при выборе например бара - менялся селект именно на бар, но сначала полный селект http://ribalka02.ru/phpsqlinfo_add.html
  • Гость: Админ, я вот ужо целый день сижу и не могу понять почему у мну не выводит на экран с базы, в таблицу сохроняет, но не выводит, не могу найти...Будь человеком кинь мылом все файлы в фул вид.
  • Гость: Вот ссылка на <a href="http://webmap-blog.ru/files/gmap/phpsqlajax_map.zip" rel="nofollow">архив</a> с файлами примера
  • Гость: Для тех, кто работает с javascript v3 новая статья: https://developers.google.com/maps/articles/phpsqlsearch_v3
  • Гость: и еще одна, более схожая по содержанию с даной: https://developers.google.com/maps/articles/phpsqlajax_v3
  • Гость: Как можно вывести метки на карту не зная широты и долготы, а зная только адрес метки?
  • Гость: Подскажите, пожалуйста, как это связать с предыдущей статьей про добавление меток?