HOW TO: Google Map aus Adressfeldern generieren
am 28.07.2007 - 16:23 Uhr in
Automatisch erzeugte Google Maps
Benötigte Module:
-Gmap
-Gmap Location
Wir möchten das der User in einem Beitrag eine Adresse eingibt und das hinterher ein passendes Google Map eingeblendet wird.
Dazu erstellen wir uns z.B. einen neuen Inhaltstypen, mit Feldern für Strasse, Hausnummer, PLZ, Ort, Land, usw.
Anschließend erstellen wir uns ein neues node.tmpl.php oder editieren unser altes.
Wir fragen die Inhalte der einzelnden Felder ab, mit:
<?php
$strasse = $node->field_strasse[0]['view'];
$hausnummer = $node->field_hausnummer[0]['view'];
$postleitzahl = $node->field_postleitzahl[0]['view'];
$ort = $node->field_ort[0]['view'];
?>
Anhand dieser Daten können wir uns die Latitude und Longitude berechnen lassen:
<?php
// Angabe deines Google Api Keys
$key ="Euren GoogleMap API Key hier eintagen, ansonsten unter google.com/apis/maps/ einen erstellen";
//Angabe der Adresse, von der die Koordinaten geholt werden sollen
$adresse="http://maps.google.com/maps/geo?q=$hausnummer+$strasse+$ort&output=xml&key=$key";
//XML File von google holen
$urlinhalt=file_get_contents($adresse);
//XML File utf8 konvertieren
$urlinhalt = utf8_decode ($urlinhalt);
//SimpleXMLElement Objekt erstellen
$xml = new SimpleXMLElement($urlinhalt);
//Koordinaten auslesen - trennen - und in 2 variablen speichern
D
list($longitude, $latitude, $altitude) = explode (",",$xml->Response->Placemark->Point->coordinates);
// Latitude ist jetzt: $latitude
// Longitide ist jetzt: $longitude
?>
Damit diese Werte hinterher auch in den Blöcken zur Verfügung stehen definieren wir sie als KONSTANTEN
<?php
define('LONGITUDE', $longitude);
define('LATITUDE', $latitude);
?>
Jetzt erstellen wir uns einen neuen Block, dessen Body folgenden Code enthält:
<?php
$longitude = LONGITUDE;
$latitude = LATITUDE;
//Koordinaten ausgeben
// Zum Testen: echo "Longitude: $longitude, Latitude: $latitude";
?>
[gmap markers=big blue::<?php print $latitude; ?>, <?php print $longitude; ?> | zoom=15 |center=<?php print $latitude; ?>, <?php print $longitude; ?> |width=100% |height=400px |id=macro_map |control=Small |type=Map]
Wichtig dabei: wir müssen dem PHP Eingabeformat auch den Gmap Filter zuweisen, damit nachher ein Gmap dargestellt wird.
Das war's auch schon alternativ kann man mit :Sprechblaseninhalt... vor | zoom= noch einen Inhalt für die Sprechblase erzeugen...
Hoffe das Hilft euch!
PS: Ich bin Designer und kein Coder, was man vielleicht an der eventuell umständlichen Herangehensweise sehen kann, es geht bestimmt noch viel einfacher, aber für mich war das die einfachste Lösung.
Verbesserungsvorschläge Willkommen!
THNX an Heine und swentel aus dem irc.freenode.net #drupal Chat
- Anmelden oder Registrieren um Kommentare zu schreiben
Leider funktioniert dieses
am 26.12.2007 - 19:01 Uhr
Leider funktioniert dieses How-to bei mir nicht. Wenn ich die Variablen $latitude und $longitude ausgebe, enthalten diese keine Werte. Hat jemand das Tutorial durchgearbeitet? Bei wem funktioniert es?
Trotz richtiger Angabe der
am 26.12.2007 - 19:16 Uhr
Trotz richtiger Angabe der Adresse samt gültigen Key bekomme ich einen 602er-Code, laut Google:
No corresponding geographic location could be found for the specified address. This may be due to the fact that the address is relatively new, or it may be incorrect.
Gebe ich dieselbe Adresse über den Browser von Hand ein, erhalte ich das gewünschte XML-Dokument mit dem 200er-Code.
Hat hier jemand eine Idee warum das so ist?
ich bekomme folgenden
am 28.03.2008 - 23:30 Uhr
ich bekomme folgenden Fehler, woran kann sowas liege?
# warning: file_get_contents(http://maps.google.com/maps/geo?q=94+Alt Nowawes+Potsdam&output=xml&key=ABQIAAAAzEke80JPrZniVXpyaJjojBQ-kumq7Zdy9GzAyI1vUlmFkiAyjxRvO5uM2_g7m26W8vW9GmhS3MsL-g) [function.file-get-contents]: failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request in /www/htdocs/w008b8c6/sites/kindaki.de/themes/zen/kids/node-kindergarten.tpl.php on line 16.
# warning: file_get_contents(http://maps.google.com/maps/geo?q=+Geiselbergstraße 12+Potsdam&output=xml&key=ABQIAAAAzEke80JPrZniVXpyaJjojBQ-kumq7Zdy9GzAyI1vUlmFkiAyjxRvO5uM2_g7m26W8vW9GmhS3MsL-g) [function.file-get-contents]: failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request in /www/htdocs/w008b8c6/sites/kindaki.de/themes/zen/kids/node-kindergarten.tpl.php on line 16.
# warning: file_get_contents(http://maps.google.com/maps/geo?q=+Seestraße 43+Potsdam&output=xml&key=ABQIAAAAzEke80JPrZniVXpyaJjojBQ-kumq7Zdy9GzAyI1vUlmFkiAyjxRvO5uM2_g7m26W8vW9GmhS3MsL-g) [function.file-get-contents]: failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request in /www/htdocs/w008b8c6/sites/kindaki.de/themes/zen/kids/node-kindergarten.tpl.php on line 16
http://www.deafvision.de
also ich bekomme das einfach
am 29.03.2008 - 11:08 Uhr
also ich bekomme das einfach nicht hin! Versuche ich die Daten mit files_get_contents zu laden bekomme ich eine Fehlermeldung! Lade ich sie mit drupal_http_request() kommt kein Fehler, aber den Zugriff auf die geladenen Daten bekomme ich dennoch nicht gebacken!
http://www.deafvision.de
Was meinst Du warum eine Konstante den Namen Konstante hat?
am 29.03.2008 - 12:31 Uhr
Deine Vorgehensweise hat leider einen Schoenheitsfehler: Du definierst Lat und long als Konstanten. Was meinst Du warum eine Konstante den Namen Konstante hat?
http://de.wikibooks.org/wiki/Websiteentwicklung:_PHP:_Konstanten
Besser waere, statt die Entwerte von Lat und Long als Kontante zu definieren sie im Nodetyp zu speichern.
Du legst im Nodetyp 2 Felder an: lat und long
Damit sie beim 1. Erstellen einer Seite und 2. der Anzeige einer Seite nicht sichtbar sind machst Du folgendes:
Zu 2. Die Anzeige dieser Felder ausblenden (Tab "Felder anzeigen")
Zu 1. Modul CCK Field permissions verwenden
Damit verbietest Du allen Usern die Anzeige der beiden Felder.
Danach hat man im Nodetyp 2 Felder die man auch ansprechen kann mit
$node->field_lat[0]['view']
$node->field_long[0]['view']
-------------
quiptime
Nur tote Fische schwimmen mit dem Strom.
Da geht noch was.
natürlich ein guter
am 29.03.2008 - 13:38 Uhr
natürlich ein guter Einwand, aber die Lösung für den eigentlichen Aufruf macht das ja leider nicht aus!
http://www.deafvision.de
mehr als nur schlechter Programmierstyl
am 29.03.2008 - 14:43 Uhr
Du hast mich nicht verstanden. Ich formuliere es deutlicher:
Deine Art und Weise bei Lat und Long Konstanten zu definieren ist mehr als nur schlechter Programmierstyl. Sag jezt nicht das Du kein PHP-Programmierer bist. Das hat damit nichts zu tun und ist nur eine Ausrede weil Du den Aufwand scheust nicht Kontanten zu verwenden. Das ist einfach nur Faulheit.
Es mag funktionieren. Du musst aber weiterhin bedenken wie Konstanten im Vergleich zu einem Feldinhalt im Speicher gehalten werden.
Stelle Dir vor Du hast 100 oder mehr Gmaps mit Deinen Usern. Dann wird sinnloserweise 100 mal oder mehr Speicher beansprucht (der Dir im ISP Account zur Verfuegung stehende Memory).
Jetzt stelle Dir vor andere unbedarfte User lesen Deinen Post hier, Du hast ihn als HowTo gekennzeichnet, und sagen sich: oh, coole Sache das mit den Konstanten.
Falls Du immer noch nicht verstehst was ich meine:
Wenn der Gmap API Key als Konstante definiert wird ist das in Ordnung. Denn den API Key gibt es nur einmal in Deinem System.
-------------
quiptime
Nur tote Fische schwimmen mit dem Strom.
Da geht noch was.
öhm hab ich was gesagt? der
am 29.03.2008 - 14:52 Uhr
öhm hab ich was gesagt? der Code da oben stammt nicht von mir... und ich nutze den auch nicht in der form. was ich nutze ist der request an google und genau der funzt eben nicht! also bitte erst lesen! ich hab nix gemacht ;o)
http://www.deafvision.de
wenn der Server beim ISP auf dem letzten Loch pfeift
am 29.03.2008 - 16:53 Uhr
@kev52,
mein letzter Post richtet sich an kloewer@drupal.org
PS
Noch was zu Konstanten und Speichernutzung
Eine Konstante wird von PHP permanent als Wert vorgehalten. Damit kann ich eine Konstante ueberall ansprechen. Nun aber die Frage. Was macht es fuer einen Sinn Konstanten mit Lat und Long vorzuhalten wenn ich gar nicht auf den Seiten bin die Lat und Long benoetigen?
Das Vorhalten der Werte definierter Konstanten geht zu Lasten des Arbeitsspeichers. Jetzt kann Jemand sagen, Na und - die paar Konstanten machen die Suppe nicht fett.
Dann sage ich zu der fetten Suppe:
Monate spaeter, viele Benutzer haben ihre Node mit einer Gmap angelegt. Es sind unter Umstaenden Hunderte von Benutzern mit einem Gmap. Dann sind es Hunderte von Konstanten, deren Werte von PHP vorgehalten werden - gleich noch im Doppelpack von Lat und Long. Und das immer und egal auf welcher Seite der Website man sich befindet. Und dann kann es sein das man sich ueber Performanceprobleme wundert wenn der Server beim ISP nicht grad absolut Highend ist oder wenn der Server auf dem letzten Loch pfeift.
Und noch was.
Nicht mal der Gmap Key des Googlemap Modules wird als Konstante definiert. Da wird eine andere Variante gewaehlt um den Key verfuegbar zu machen (variable_set).
-------------
quiptime
Nur tote Fische schwimmen mit dem Strom.
Da geht noch was.
so... jetzt hab ich den
am 29.03.2008 - 19:16 Uhr
so... jetzt hab ich den Fehler allein behoben ;o)
<?php
$street = $node->field_street[0]['view'];
$number = $node->field_number[0]['view'];
$zipcode = $node->field_zipcode[0]['view'];
$city = $node->field_city[0]['view'];
$address = '';
$address .= $street;
$address .= ', ';
$address .= $city;
$address .= ', ';
$address .= $zipcode;
// Angabe deines Google Api Keys
$key ="ABQIAAAAzEke80JPrZniVXpyaJjojBQ-kumq7Zdy9GzAyI1vUlmFkiAyjxRvO5uM2_g7m26W8vW9GmhS3MsL-g";
//Angabe der Adresse, von der die Koordinaten geholt werden sollen
$url='http://maps.google.com/maps/geo?output=xml&key='. $key .'&q=';
//XML File von google holen
$urlcontent = file_get_contents($url . urlencode($address));
//XML File utf8 konvertieren
$urlcontent = utf8_decode ($urlcontent);
//SimpleXMLElement Objekt erstellen
$xml = new SimpleXMLElement($urlcontent);
//Koordinaten auslesen - trennen - und in 2 variablen speichern
list($longitude, $latitude, $altitude) = explode (",",$xml->Response->Placemark->Point->coordinates);
?>
das ist natürlich nur erstmal ein rohtest in der tpl.php
meine Frage wäre jetzt wie ich am besten dafür sorge, dass beim speichern des nodes die Werte erfasst werden.
Sollte ich dafür ein Modul schreiben oder gibt es noch einen besseren Weg das zu machen?
http://www.deafvision.de
Egal was und wie Du es tun
am 29.03.2008 - 21:25 Uhr
Egal was und wie Du es tun willst. Einen Tipp moechte ich Dir geben und Du tust gut daran ihn zu beachten.
Speichere die Werte von Lat und Long!
Warum?
Wenn man bei Google in zu kurzem Abstand hintereinander Lat Long Werte abfragt wird der API Key fuer die betreffende Website gesperrt. Und zwar sofort.
Da reichen bereits 2 aufeinanderfolgende Abfragen im Sekundentakt aus. Das kann ganz schnell passieren wenn 2 Benutzer unmittelbar hintereinander ihre Node mit dem Gmap speichern - da hat man Pech gehabt.
Und erst recht bei der Eingangs in diesem HowTo beschriebenen Vorgehensweise. Da bei der Beschreibung Lat und Long nur als Konstanten existieren, also nie gespeichert werden wird also immer wieder Lat und Long bei Google abgefragt damit die Konstanten gefuellt werden koennen.
Was kannst Du tun?
Du erstellst wie gesagt einen eigenen Inhaltstyp fuer die Nodes mit einem Gmap. Diese Nodes bekommen neben den Adressfelder auch 2 Felder fuer Lat und Long. In diesen Feldern werden die auf der Basis der Adressfelder ermittelten Werte von Lat und Long eingetragen. Das muss also beim Speichern (Erstellung bzw. Aenderung) einer Node dieses Typs erfolgen.
Und das ist die eigentliche Aufgabe!
Beim Speichervorgang der Node zuerst die Werte der Adressfelder zu Goggle senden, die Werte fuer Lat und Long zurueckbekommen und danach den eigentlichen Speichervorgang der Node durchfuehren. Aber das kriegt Du nicht geregelt - in den Speichervorgang der Node einzugreifen.
Also muss man zu einem anderen Zeitpunkt die Lat und Long Abfrage bei Google durchfuehren.
Und hier die Loesung fuer den anderen Zeitpunkt. Sie liegt im Template!
Im zu diesem Nodetyp gehoerenden Template, ohne ein solches wirst Du auf keinen Fall auskommen, wird bei der Zusammenstellung des HTML-Code fuer die Anzeige des Googlemap folgendes passieren:
Du pruefst ob die beiden Felder fuer Lat und Long Inhalt haben. Wenn ja kannst Du sofort den HTML-Code fuer das Googlemap zusgeben.
Wenn nicht, dann dann und esrt zu diesem Zeitpunkt erfolgt auf der Basis der Werte der Adressfelder di Anfrage bei Google zum Ermitteln von Lat und Long. Danach werden diese beiden Werte in die Felder fuer Lat und Long eingetragen. Und danach sind diese beiden Felder gefuellt und Du kannst mit dem Inhalt der Felder den HTML-Code des Gmap ausgeben.
Bis hier her sollte das Ganze funktionieren. Jetzt aber die Variante wenn ein User seine Adressdate geaendert hat.
Dann wuerde ohne weitere Vorkehrungen niemals die Gmap mit den geaenderten Adressdaten angezeigt werden da die Pruefung der Felder Lat und Long ergibt das sie Inhalt haben. Und zwar den Inhalt der vorherigen Adresse.
Jetzt wird es ein wenig kompliziert.
Du brauchst also ein weitereres Feld. Dieses Feld wird nie angezeigt - auch nicht beim Erstellen oder Bearbeiten der Node. Dieses Feld protokolliert lediglich auf gewisse Weise die Anzahl der Speichervorgaenge einer solchen Node. Gesteuert wird dieses Feld in Deinem Nodetyp durch ein CCK computed field.
Ein CCK computed field ist von Haus aus beim Bearbeiten einer Node nicht sichtbar. Fuer die Anzeige der Node wird es deaktiviert (versteckt).
In solch einem Feld kann man mittels PHP-Code beliebige Felder in Nodes ansprechen. Du Computed field selbst wird mit seinem Inhalt das zusaetzliche Steuerfeld.
Eine Node hat immer ein Erstellungsdatum und ein Aktualisierungsdatum.
Beim Erstellen einer Node ist das Feld mit Aktualisierungsdatum leer. Und genau hier setzt das Computed field an. Wird eine Node geaendert wird in das Computed field zusaetzlich das Aktualisierungsdatum eingetragen - aber nicht bei der ersten Aenderung (wenn die Node noch kein Aktualisierungsdatum hat).
Wird eine Node erneut geaendert dann wird das zur Node gehoerende "alte" Aktualisierungsdatum im Computed field eingetragen. Die Node selbst traegt sich bei erneutem Speichern ihr neueres Aktualisierungsdatum ein.
Damit tritt in diesem Fall Folgendes ein. Die Node hat ein neues Aktualisierungsdatum waehrend das Computed field das alte Aktualisierungsdatum enthaelt. Und das ist logischerweise pruefbar bevor der HTML-Code fuer die Gmap ausgegeben wird. Damit kann ein Node beliebig oft geaendert werden. Gibt es eine Diffrenz zwischen den beiden Aktualisierungsdaten werden die Werte fuer Lat und Long erneut bei Google ermittelt und vorhandene Werte der Felder von Lat und Long ueberschrieben.
So, ich weiss das liest sich Jetzt kompliziert. Besonders dann wenn man noch nicht mit einem Computed field gearbeitet hat.
Altenative zu meinem Loesungsansatz ist: Schreibe Dir ein Modul.
Mit einem eigenen Modul brauchst Du kein Template und Du kannst den Speichervorgang der Node selbst bestimmen.
-------------
quiptime
Nur tote Fische schwimmen mit dem Strom.
Da geht noch was.
so kompliziert ließt sich
am 31.03.2008 - 08:36 Uhr
so kompliziert ließt sich das nicht, keine Sorge. Wie gesagt das How To da oben stammt nicht von mir... was mich daran interessiert hat war nur der Aufruf an Google. Im nachhinein ist mir auch aufgefallen, dass ich nur mal im Quelltext von Location hätte gucken müssen ;o) so hab ich ja dann auch mein Problem gelöst.
Die aktuelle Frage war auch nur darauf bezogen ob es nen besseren Weg gäbe als eben ein Modul zu proggen. Die hast du mir ja sehr ausführlich beantwortet wofür ich dir auch danken möchte.
Das fertige Modul werde ich dann auch mal veröffentlichen, denn alles was ich bisher zum Thema Google Map gefunden habe war meist zu komplex oder nicht das richtige für eine einfache Nutzer freundliche Darstellung.
http://www.deafvision.de
Gibt es Neuigkeiten, was
am 24.07.2008 - 10:10 Uhr
Gibt es Neuigkeiten, was diese Aufgabenstellung betrifft?
@quiptime: Es wäre toll, wenn Du die Lösung als Schritt-für-Schritt-Anleitung (samt Code) in einem neuen Thread formulieren oder das Modul schreiben und online stellen würdest!
lg Fritz