Отсебятина
А вот и перевод третьего урока по Google Maps API. Этот урок — как видно из названия — посвящен созданию карт при помощи данных, хранящихся в БД. Как и предыдущие — кросс-пост из моего блога.
Этот урок предназначен для людей, знакомых со связкой PHP/MySQL и желающих научиться использовать Google Maps API вместе с базами данных MySQL. После завершения этого урока у Вас будет карта, основанная на базе данных. На карте будут расположены маркеры разных цветов. Одни из них будут указывать на рестораны, другие – на бары. При клике по маркеру будет появляться инфо-окно, показывающее название места и его адрес.
Урок разбит на следующие параграфы:
- Создание таблицы БД;
- Наполнение таблицы;
- Вывод информации в XML с помощью PHP;
- Создание карты.
СОЗДАНИЕ ТАБЛИЦЫ
Когда создаете таблицу, прежде всего, Вы должны уделить внимание параметрам
lat
(широта) и lng
(долгота) карты. При текущей разрешающей способности Google Maps нам понадобятся только 6 цифр после десятичного знака. Чтобы свести дисковое пространство, занимаемое БД к минимуму, для значений lat
(широты) и lng
(долготы) рекомендуется выбрать тип данных FLOAT
с параметром 10,6. Этот тип позволяет хранить до 6-ти знаков после запятой и до 4-х перед запятой, например -123,456789 градуса. Ваша таблица должна иметь поле id
, которое будет первичным ключом для доступа к записям, а также – поле type
, в котором будет записан тип заведения (ресторан или бар).Примечание: в этом уроке используются места, значения широты и долготы которых уже известно и используются для нанесения маркеров на карту. Если же Вы попробуете использовать свою информацию, не имея данных о координатах места, то воспользуйтесь сервисом геокодинга для преобразования адреса места в его координаты. Вот список некоторых геокодинг-сервисов: http://groups.google.com/group/Google-Maps-API/web/resources-non-google-geocoders.
Если Вы предпочитаете создавать таблицы в БД с помощью phpMyAdmin, то ниже расположен скриншот создания таблицы:
Если же Вы не имеете доступ к phpMyAdmin или отдаете предпочтение чистому SQL, то ниже приведен код SQL-запроса:
CREATE TABLE `markers` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR( 60 ) NOT NULL,
`address` VARCHAR( 80 ) NOT NULL,
`lat` FLOAT( 10, 6 ) NOT NULL,
`lng` FLOAT( 10, 6 ) NOT NULL,
`type` VARCHAR( 30 ) NOT NULL
) ENGINE = MYISAM ;
НАПОЛНЕНИЕ ТАБЛИЦЫ
После создания таблицы пришло время наполнить ее информацией. Данные о 10 заведениях Сиэтла приведены ниже. В phpMyAdmin Вы можете использовать опцию ИМПОРТ для того, чтобы вставить в таблицу данные, хранящиеся в различных форматах, включая и CSV. Приложения MS Excel и Google Spreadsheets поддерживают экспорт данных в CSV-формат. Так что Вы легко можете передавать данные из этих приложений в БД MySQL, используя опции экспорта/импорта.
Вот информация, представленная в формате CSV:
Pan Africa Market," 1521 1st Ave, Seattle, WA",47.608941,-122.340145,restaurant
Buddha Thai & Bar," 2222 2nd Ave, Seattle, WA",47.613591,-122.344394,bar
The Melting Pot," 14 Mercer St, Seattle, WA",47.624562,-122.356442,restaurant
Ipanema Grill," 1225 1st Ave, Seattle, WA",47.606366,-122.337656,restaurant
Sake House," 2230 1st Ave, Seattle, WA",47.612825,-122.34567,bar
Crab Pot," 1301 Alaskan Way, Seattle, WA",47.605961,-122.34036,restaurant
Mama's Mexican Kitchen," 2234 2nd Ave, Seattle, WA ",47.613975,-122.345467,bar
Wingdome," 1416 E Olive Way, Seattle, WA",47.617215,-122.326584,bar
Piroshky Piroshky," 1908 Pike pl, Seattle, WA",47.610127,-122.342838,restaurant
А вот скриншот, показывающий импорт данных из CSV в таблицу БД:
Если же Вы не используете phpMyAdmin, то ниже расположен код запроса к БД на языке SQL:
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Pan Africa Market', '1521 1st Ave, Seattle, WA', '47.608941', '-122.340145', 'restaurant');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Buddha Thai & Bar', '2222 2nd Ave, Seattle, WA', '47.613591', '-122.344394', 'bar');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`, `type`) VALUES ('The Melting Pot', '14 Mercer St, Seattle, WA', '47.624562', '-122.356442', 'restaurant');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Ipanema Grill', '1225 1st Ave, Seattle, WA', '47.606366', '-122.337656', 'restaurant');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Sake House', '2230 1st Ave, Seattle, WA', '47.612825', '-122.34567', 'bar');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Crab Pot', '1301 Alaskan Way, Seattle, WA', '47.605961', '-122.34036', 'restaurant');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Mama Mexican Kitchen', '2234 2nd Ave, Seattle, WA', '47.613975', '-122.345467', 'bar');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Wingdome', '1416 E Olive Way, Seattle, WA', '47.617215', '-122.326584', 'bar');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`, `type`) VALUES ('Piroshky Piroshky', '1908 Pike pl, Seattle, WA', '47.610127', '-122.342838', 'restaurant');
ВЫВОД ИНФОРМАЦИИ В XML C ПОМОЩЬЮ PHP
К этому моменту у Вас должна быть таблица (которая называется markers) базы данных, заполненная данными. Сейчас Вам нужно написать некоторый PHP-код, который позволит подключиться к БД, взять из нее необходимую информацию и экспортировать ее в XML-файл, с которым будет взаимодействовать карта с помощью асинхронных JavaScript-запросов. Если же Вы никогда не писали на PHP код, позволяющий подключиться к БД, то Вам необходимо посетить сайт php.net и почитать о функциях
mysql_connect()
, mysql_select_db()
, my_sql_query()
, и mysql_error()
.Примечание: некоторые уроки предлагают Вам создать страницу с картой как PHP-файл и использовать JavaScript для вывода каждого маркера в отдельности. Такой подход может быть проблематичен. Используя же XML-файл в качестве посредника между БД и картой, Вы ускоряете первоначальную загрузку страницы и облегчаете себе отладку приложения. Вы можете проверять данные, записанные из БД в XML-файл и результат анализа этого файла на JavaScript. И на любой стадии Вы можете обойтись без БД, управляя картой только с помощью статичного XML-файла.
Во-первых, Вы должны вынести информацию о подключении к БД в отдельный файл. Ниже приведен PHP-код, в котором Вы должны прописать собственные имя пользователя, пароль и имя БД:
<?
$username="username";
$password="password";
$database="username-databaseName";
?>
Использование XML-функций PHP для создания 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-код должен быть похож на тот, что представлен ниже:
<?php
require("phpsqlajax_dbinfo.php");
// Создание XML-файла и родительского элемента
$doc = domxml_new_doc(" 1.0 ");
$node = $doc->create_element("markers");
$parnode = $doc->append_child($node);
// Открытие соединения с MySQL-сервером
$connection=mysql_connect (localhost, $username, $password);
if (!$connection) {
die('Нет соединения : ' . mysql_error());
}
// Подключение к конкретной БД
$db_selected = mysql_select_db($database, $connection);
if (!$db_selected) {
die ('Невозможно использовать БД : ' . mysql_error());
}
// Выборка всех записей из таблицы markers
$query = "SELECT * FROM markers WHERE 1"
$result = mysql_query($query);
if (!$result) {
die('Неверный запрос: ' . mysql_error());
}
header("Content-type: text/xml");
// Цикл прохода по всем выбранным записи; создание узла для каждой
while ($row = @mysql_fetch_assoc($result)){
// Добавление нового узла в XML
$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;
?>
Использование PHP-функции echo для создания XML-файла
Если Вы не имеете доступ к функциям
dom_xml
, то XML-файл можно создать с помощью функции echo
. При использовании функции echo
нужно будет написать функцию-помощник (например, parseToXML
), которая будет декодировать некоторые специальные символы (>,<,’,”), чтобы не возникало ошибок XML.В PHP, для начала, нужно подключиться к БД и произвести выбор необходимых данных при помощи запроса вида
SELECT *
(выбрать все) к таблице с именем “markers”
и пройтись по всем результатам этой выборки. Затем необходимо вывести родительский узел при помощи функции echo
и пройтись по результатам выборки. При этом необходимо использовать написанную нами функцию parseToXML
. Выполнение этого скрипта должно закончиться выводом закрывающего тэга markers
.Примечание: если в БД Вы используете международные символы, то нужно применить кодировку UTF-8 к выводимым данным. Вот функция перекодировки в UTF-8.
Ваш PHP-код должен быть похож на тот, что представлен ниже:
<?php
require("phpsqlajax_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;
}
// Открываем соединение с MySQL-сервером
$connection=mysql_connect (localhost, $username, $password);
if (!$connection) {
die('Нет соединения : ' . mysql_error());
}
// Устанавливаем соединение с БД
$db_selected = mysql_select_db($database, $connection);
if (!$db_selected) {
die ('Невозможно использовать БД : ' . mysql_error());
}
// Выборка всех записей из таблицы markers
$query = "SELECT * FROM markers WHERE 1"
$result = mysql_query($query);
if (!$result) {
die('Неверный запрос: ' . mysql_error());
}
header("Content-type: text/xml");
// Создание XML-кода, вывод родительского элемента
echo '<markers>';
// Цикл прохода по всем выбранным записи; создание узла для каждой
while ($row = @mysql_fetch_assoc($result)){
// Вывод нового узла XML
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>';
?>
Использование DOM-функций PHP для создания XML-файла
Во-первых, необходимо убедиться в том, что Вы используете PHP версии 5. Если Ваша версия PHP ниже, то используйте какой-либо из предыдущих способов.
В PHP, для начала, нужно инициализировать новый XML-документ и создать родительский узел “markers”. Затем нужно подключиться к БД и произвести выбор необходимых данных при помощи запроса вида
SELECT *
(выбрать все) к таблице с именем “markers” и пройтись по всем результатам этой выборки. Для каждой записи в таблице (каждого заведения) будет создаваться свой узел в XML-документе, атрибуты которого будут полями из соответствующей записи таблицы, — этот узел будет присоединяться к родительскому узлу. После этого Вы получите готовый XML-документ.Примечание: если в БД Вы используете международные символы, то нужно применить кодировку UTF-8 к выводимым данным. Вот функция перекодировки в UTF-8.
<?php
require("phpsqlajax_dbinfo.php");
// Создание XML-файла и родительского элемента
$dom = new DOMDocument(" 1.0 ");
$node = $dom->createElement("markers");
$parnode = $dom->appendChild($node);
// Открытие соединения с MySQL-сервером
$connection=mysql_connect (localhost, $username, $password);
if (!$connection) { die(' Нет соединения: ' . mysql_error());}
// Подключение к конкретной БД
$db_selected = mysql_select_db($database, $connection);
if (!$db_selected) {
die ('Невозможно использовать БД : ' . mysql_error());
}
// Выборка всех записей из таблицы markers
$query = "SELECT * FROM markers WHERE 1"
$result = mysql_query($query);
if (!$result) {
die('Неверный запрос: ' . mysql_error());
}
header("Content-type: text/xml");
// Цикл прохода по всем выбранным записи; создание узла для каждой
while ($row = @mysql_fetch_assoc($result)){
// Добавление нового узла в XML
$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
Запустите этот скрипт, чтобы убедиться в правильности результатов вывода. Если существуют какие-нибудь проблемы с подключением к БД, то можно попробовать удалить строку с заголовком содержимого (text/xml), т.к. она может мешать Вашему браузеру отображать сообщения об ошибках.
Если же скрипт правильно выполнил свою работу, то Вы должны увидеть следующее:
<markers>
<marker name=" Pan Africa Market" address=" 1521 1st Ave, Seattle, WA" lat=" 47.608940" lng=" -122.340141" type=" restaurant"/>
<marker name=" Buddha Thai & Bar" address=" 2222 2nd Ave, Seattle, WA" lat=" 47.613590" lng=" -122.344391" type=" bar"/>
<marker name=" The Melting Pot" address=" 14 Mercer St, Seattle, WA" lat=" 47.624561" lng=" -122.356445" type=" restaurant"/>
<marker name=" Ipanema Grill" address=" 1225 1st Ave, Seattle, WA" lat=" 47.606365" lng=" -122.337654" type=" restaurant"/>
<marker name=" Sake House" address=" 2230 1st Ave, Seattle, WA" lat=" 47.612823" lng=" -122.345673" type=" bar"/>
<marker name=" Crab Pot" address=" 1301 Alaskan Way, Seattle, WA" lat=" 47.605961" lng=" -122.340363" type=" restaurant"/>
<marker name=" Mama's Mexican Kitchen" address=" 2234 2nd Ave, Seattle, WA" lat=" 47.613976" lng=" -122.345467" type=" bar"/>
<marker name=" Wingdome" address=" 1416 E Olive Way, Seattle, WA" lat=" 47.617214" lng=" -122.326584" type=" bar"/>
<marker name=" Piroshky Piroshky" address=" 1908 Pike pl, Seattle, WA" lat=" 47.610126" lng=" -122.342834" type=" restaurant"/>
</markers>
СОЗДАНИЕ КАРТЫ
Раз XML-файл правильно отображается в браузере, то пришло время создать карту, используя JavaScript. Если Вы никогда не имели дела с Google Maps API, то изучите, пожалуйста, основы при помощи официальной документации.
Подгрузка XML-файла
Для того, чтобы загрузить XML-файл на страницу, необходимо использовать API-функцию
GDownloadURL
. GDownloadURL
является как бы оболочкой для метода XMLHttpRequest
, который используется для отправки запросов в XML-форме. Первым параметром функции GDownloadURL
является путь к XML-файлу. Второй же параметр – это функция, которая будет выполняться при получении ответа от XML.Примечание: очень важно понять, что
GDownloadURL
работает асинхронно – функция, являющаяся вторым параметром GDownloadURL
, не будет срабатывать, как только Вы применили этот метод. Чем объемней Ваш XML-файл, тем больше потребуется времени для вызова этой функции-параметра. Не следует помещать никакого кода, отвечающего за размещение маркеров на карте, после метода GDownloadURL
– его нужно помещать в функцию-параметр.Функция-параметр необходима для того, чтобы отыскать все элементы “markers” в XML. Для каждого маркера мы восстанавливаем значения названия, адреса, типа и координат, а затем мы передаем эти значения функции
creatMarker
, которая помещает маркеры на карту.GDownloadUrl("phpsqlajax_genxml.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
для определения произваольных изображений, которые будут отображаться в качестве маркера. Для начала определим два объекта: 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 customIcons = [];
customIcons["restaurant"] = iconBlue;
customIcons["bar"] = iconRed;
Создание маркеров и инфо-окон
Вы должны поместить весь код, который необходим для создания маркеров в функцию
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-файл отображается в браузере корректно.А вот и ссылка на готовый пример.
Счасливого Вам коддинга!