chevron-left chevron-right

[PHP][JS] Google Maps i znaczniki miejsc pobierane z bazy danych MySQL

Google Maps jest bardzo popularnym narzędziem do odnajdywania miejsc czy wyznaczania trasy. To wszyscy wiemy. Wiemy też, że bardzo wiele serwisów korzysta z Google Maps by wstawiać do nich znaczniki z lokalizacją różnych firm czy po prostu z lokacją swojej siedziby tylko po to, aby osoba korzystająca z serwisu wiedziała, gdzie takie miejsce się znajduje.
W tym artykule dowiesz się jak stworzyć mapę do której znaczniki będą wczytywane z bazy danych MySQL za pomocą PHP i AJAXa oraz Google Maps API.

1. Tworzymy bazę danych MySQL

Tworzymy tabelę o nazwie google_maps za pomocą takiego zapytania SQL:

CREATE TABLE IF NOT EXISTS `google_maps` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `nazwa` VARCHAR(255) NOT NULL,
  `adres` VARCHAR(255) NOT NULL,
  `lat` FLOAT(10,6) NOT NULL,
  `lng` FLOAT(10,6) NOT NULL,
  `typ` VARCHAR(255) NOT NULL,
  PRIMARY KEY (`id`)
Teraz, gdy mamy już stworzoną strukturę tabeli to możemy przystąpić do dodawania własnych lokacji do tabeli lub wykorzystaj mój przykład:
INSERT INTO `google_maps` (`id`, `nazwa`, `adres`, `lat`, `lng`, `typ`) VALUES
(1, 'Szkoła Podstawowa nr 6', 'Wawel 13, Sosnowiec', 52.025459, 19.204102, 'szkoła'),
(2, 'Helios', 'Modrzejowska 32, Sosnowiec', 50.276367, 19.130651, 'kino'),
(3, 'Stadion Zimowy', 'Zamkowa 14, Sosnowiec', 50.282719, 19.144085, 'sport'),
(4, 'Pub Zakręcona', 'Małachowskiego 9, Sosnowiec', 50.276958, 19.131124, 'pub'),
(5, 'Pub Rubieże', 'Modrzejowska 39, Sosnowiec', 50.275600, 19.131746, 'pub'),
(6, 'IV Liceum Ogólnokształcące im. St. Staszica', 'Zillingera 1, Sosnowiec', 50.284199, 19.130030, 'szkoła'),
(7, 'Stadion Ludowy', 'Kresowa 1, Sosnowiec', 50.283031, 19.103456, 'sport');
To będzie wszystko jeśli chodzi o budowę i zapełnienie bazy danych

2. Połączenie z bazą danych - plik db.php

Następnym krokiem jest stworzenie pliku który będzie zawierał dane do połączenia się z bazą danych.
Kod takiego pliku wygląda następująco:

< ?php
$username="login do bazy";
$password="hasło do bazy";
$database="nazwa bazy danych";
?>
Tylko tyle i aż tyle. Myślę, że nie trzeba komentować tego pliku.

3. Generator pliku XML na podstawie danych z bazy MySQL - plik generatorXML.php

< ?php
//Pobiera dane do połączenia z bazą danych
require('db.php');
 
 
//Funkcja parsująca znaki do standardu ASCII, który jest potrzebny dla pliku XML. To też jest zabezpieczenie przed próbą wpisania kodu wykonującego.
function parseToXML($htmlStr) 
{ 
	$xmlStr=str_replace("<",'&lt;',$htmlStr); 
	$xmlStr=str_replace(">",'&gt;',$xmlStr); 
	$xmlStr=str_replace('"','&quot;',$xmlStr); 
	$xmlStr=str_replace("'",'&apos;',$xmlStr); 
	$xmlStr=str_replace("&",'&amp;',$xmlStr);
	$xmlStr=str_replace("$",'&#036;',$xmlStr);
	$xmlStr=str_replace("%",'&#037;',$xmlStr);
	$xmlStr=str_replace("(",'&#040;',$xmlStr);
	$xmlStr=str_replace(")",'&#041;',$xmlStr);
	$xmlStr=str_replace("[",'&#091;',$xmlStr);
	$xmlStr=str_replace("]",'&#093;',$xmlStr);
	$xmlStr=str_replace("{",'&#123;',$xmlStr);
	$xmlStr=str_replace("}",'&#125;',$xmlStr);
return $xmlStr; 
}
 
//Otwiera połączenie z serwerem baz danych MySQL
$connection=mysql_connect (localhost, $username, $password);
if (!$connection) {
	die ('Nie połączono z serwerem baz danych: '. mysql_error());
}
 
//Wybiera bazę danych z serwera
$db_selected = mysql_select_db($database, $connection);
if (!$db_selected) {
	die ('Nie można połączyć się z bazą danych: '. mysql_error());
}
 
//Pobieranie znacznika z tabeli. Dane są pobierane pojedynczo.
$query = "SELECT * FROM google_maps WHERE 1";
mysql_query('SET character_set_connection=utf8');
mysql_query('SET character_set_client=utf8');
mysql_query('SET character_set_results=utf8'); 
$result = mysql_query($query);
if (!$result) {
	die('Niepoprawne zapytanie do bazy: '. mysql_error());
}
 
//Tworzy plik XML
echo '<znaczniki>';
 
//Tworzy kolejne, pojedyncze wpisy do pliku XML
while ($row = @mysql_fetch_assoc($result)) {
	//Dodawanie atrybutów do znacznika
	echo '<znacznik ';
	echo 'nazwa="' . parseToXML($row['nazwa']) . '" ';
	echo 'adres="' . parseToXML($row['adres']) . '" ';
	echo 'lat="' . $row['lat'] . '" ';
	echo 'lng="' . $row['lng'] . '" ';
	echo 'typ="' . $row['typ'] . '" ';
	echo '/>';
}
 
//Zamyka plik XML
echo '</znaczniki>';
 
?>
Kod został opisany dość dokładnie. Dodam, że jeśli nie dodasz do kodu wpisów z mysql_query('SET ... ') to wtedy zaczynają się problemy z polskimi znakami odczytywanymi z bazy danych. Możliwe, że ten kod nie będzie Ci wogóle potrzebny, ale na potrzeby tego przykładu dodałem go, tak na wszelki wypadek.

4. Struktura HTML - plik index.html

<body onLoad="load()"> 	
	<div id="map">
    </div>
</body>
Jak to bywa w moich tutorialach, kod HTML nie jest jakiś wypasiony. To jest jego zaleta. Dzięki temu łatwo można zrozumieć mechanizmy.
W powyższym kodzie, mapa jest uruchamiana funkcją load() i będzie wczytywana do diva o nazwie map.

5. Kod generujący mapę i znaczniki - wstawiamy do sekcji HEAD.

//Baza ikonek do oznaczenia miejsc wedle typu
var ikonki = {
	pub: {
		icon: 'bar.png',
		shadow: 'shadow.png'
	},
	szkoła: {
		icon: 'school.png',
		shadow: 'shadow.png'
	},
	sport: {
		icon: 'stadium.png',
		shadow: 'shadow.png'
	},
	kino: {
		icon: 'cinema.png',
		shadow: 'shadow.png'
	}
};
//Ładuje znaczniki na mapę
function load() {
	//Ustawia środek mapy w wybranej pozycji, ustawia zoom mapy i jej typ -  w tym przypadku wskazuje na Sosnowiec
	var map = new google.maps.Map(document.getElementById("map"), {
		center: new google.maps.LatLng(50.286264, 19.104079),
		zoom: 13,
		mapTypeId: 'roadmap'
	});
	var dymekInfo = new google.maps.InfoWindow;
 
	//Pobiera nazwę pliku generującego XML
	pobierzAdres("generatorXML.php", function(data) {
		var xml = parseXml(data);
		//Zczytuje dane z pliku XML
		var znaczniki = xml.documentElement.getElementsByTagName("znacznik");
		for (var i = 0; i < znaczniki.length; i++) {
			var nazwa = znaczniki[i].getAttribute("nazwa");
			var adres = znaczniki[i].getAttribute("adres");
			var typ = znaczniki[i].getAttribute("typ");
			var wspolrzedne = new google.maps.LatLng(
			parseFloat(znaczniki[i].getAttribute("lat")),
			parseFloat(znaczniki[i].getAttribute("lng")));
			//Buduje strukturę wyświetlanego elementu
			var html = "<b>" + nazwa + " <br />" + adres;
			var ikona = ikonki[typ] || {};
			var znacznik = new google.maps.Marker({
				map: map,
				position: wspolrzedne,
				icon: ikona.icon,
				shadow: ikona.shadow
			});
			laczenieDanych(znacznik, map, dymekInfo, html);
		}
	});
}
 
//Funkcja wiążąca znaczniki z mapą
function laczenieDanych(znacznik, map, dymekInfo, html) {
	google.maps.event.addListener(znacznik, 'click', function() {
		dymekInfo.setContent(html);
		dymekInfo.open(map, znacznik);
	});
}
 
//Wywołanie połączenia za pomocą AJAXa
function pobierzAdres(url, callback) {
	var request = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest;
 
	request.onreadystatechange = function() {
		if (request.readyState == 4) {
			request.onreadystatechange = nicNieRob();
			callback(request.responseText, request.status);
		}
	};
 
	request.open('GET', url, true);
	request.send(null);
}
 
//Funkcja parsująca XML
function parseXml(str) {
	if (window.ActiveXObject) {
		var doc = new ActiveXObject('Microsoft.XMLDOM');
		doc.loadXML(str);
		return doc;
	}
	else if (window.DOMParser) {
		return (new DOMParser).parseFromString(str, 'text/xml');
	}
}
 
function nicNieRob() {}
Kod został objaśniony komentarzami. Ten kod wstawiamy do sekcji head jako kod javascript.
Należy pamiętać, aby wstawić do sekcji head API dla Google Maps jako kod javascript, co wygląda tak:
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>

6. Style dla mapy - plik styl.css

body {
	width: 800px;
	margin: 50px auto;
	padding: 0;
	font-family: Arial, Helvetica, sans-serif;
}
h1 {
	font-size: 20px;
	text-align: center;
}
#map {
	width: 640px;
	height: 480px;
	margin: auto;
}

To byłoby na tyle. Mam nadzieję, że to wszystko się przyda Tobie 🙂

  • jcoffee

    Dzięki 🙂 Przydało się

  • jcoffee

    W 1 kodzie jak tworzysz tabelę dodaj nawias ) na końcu 😉

  • Paweł

    Dobre, dobre i pomocne, tylko brakuje tu czegos co by generowalo szerokosc i dlugosc… tzn jakis formularz i mapka okreslenia swojej lokalizacji i lokalizacja wysylana do bazy, chodzi o parametr lat i lng

  • sickie

    Skoro mamy już to wszystko, to czas na panel, w którym wpiszemy dane miejscowości do formularza, skrypcik odpyta serwer google i przyjmie dane od niego, zapisze je w bazie danych 🙂

  • myślę, że to już jest miejsce na Twoją inwencję 😉
    jeśli będziesz chciał się podzielić sposobem na zrobienie tego to daj znać 🙂

  • zola

    A mi generatorXML jak nie skasuję spacji w <? php nie działa 🙁 a jak skasuje wywala masę błędów. A projekt muszę oddać do soboty ;(

  • tam masz podany przykład, który działa
    musisz poszukać w którym miejscu masz błąd

  • Dzięki. Ale ja to zrobię inaczej. Do generowania kodu XML użyję DOMDocument, a długość i szerokość geograficzną będę pobierał z Google. Jak się uda…
    I mam jeszcze jedno „zapytańsko”. Gdzie jest powiedziane jaka jest szerokość i dł. geograficzna (północna czy południowa; wschodnia czy zachodnia)?

  • te namiary geograficzne pobieram ręcznie z Google Maps

  • SpeX

    A ja mam pytanie, jak ograniczyć pobieranie obrazków w zależności od zooma mapki?

  • Musisz zrobić pętlę sprawdzającą zoom i zależnie od stopnia zoomu wyświetlić liczbę elementów na mapie. Dawno nie bawiłem się API od Google Maps i nie pamiętam jak to sprawdzić.

  • JKF

    Nie chce działać na IE7 🙁

  • Mikel

    Super! Mam pytanie – jak zrobić filtr pokazujący tylko wybrane miesjca (np. same szkoły) ? Pozdrawiam

  • Piotr Nalepa

    Na chwilę obecną nie jestem w stanie wskazać poprawną odpowiedź ze względu na okres czasu jaki minął od momentu gdy pracowałem z Google Maps API. Zajrzyj do dokumentacji Google Maps API. Na pewno znajdziesz tam wskazówki a być może nawet odpowiedź na Twoje pytanie 😉