В предыдущей заметке мы реализовали возможность добавления меток на карту пользователями.
В этой я расскажу, как можно осуществить вывод введенных данных на карту 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('<','<',$htmlStr); $xmlStr=str_replace('>','>',$xmlStr); $xmlStr=str_replace('"','"',$xmlStr); $xmlStr=str_replace("'",''',$xmlStr); $xmlStr=str_replace("&",'&',$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&v=2&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
Админ, я вот ужо целый день сижу и не могу понять почему у мну не выводит на экран с базы, в таблицу сохроняет, но не выводит, не могу найти…Будь человеком кинь мылом все файлы в фул вид.
Вот ссылка на архив с файлами примера
Для тех, кто работает с javascript v3 новая статья: https://developers.google.com/maps/articles/phpsqlsearch_v3
и еще одна, более схожая по содержанию с даной: https://developers.google.com/maps/articles/phpsqlajax_v3