Smarty foreach / Google Mapps DistanceMatrix API

demo1987

Mitglied
Hallo,

ich habe eine kleine Seite mit Smarty (version 3) als templatesystem.

In einer tpl hole ich mir per foreach die einträge aus einer sql tabele und lege für jede eine neue tabellen-zeile an:
HTML:
<tbody>
                            {foreach $dispatches as $dispatch}
                            	<tr>
                                    <td class="text-center"><input type="checkbox" id="checkbox1-1" name="checkbox1-1"></td>
                                    <td class="text-center">{$dispatch.id}</td>
                                    <td>{$dispatch.dispatch_time|date_format:"%d.%m.%Y, %H:%M:%S"}</td>
                                    <td><a href="../admin/mission.php?id={$missions_eintrag.id}">{$dispatch.device_id}</a></td>
                                    <td>{$dispatch.lat}&nbsp;/&nbsp;{$dispatch.long}</td>
                                    <td><div id="outputDiv" ></div></td>
                                    <td class="text-center">
                                        <div class="btn-group btn-group-xs">
                                            <a href="../admin/editmission.php?do=edit&id={$missions_eintrag.id}" data-toggle="tooltip" title="" class="btn btn-default" data-original-title="Bearbeiten"><i class="fa fa-pencil"></i></a>
                                            <a href="../admin/editmission.php?do=delete&id={$missions_eintrag.id}" data-toggle="tooltip" title="" class="btn btn-default" data-original-title="L&ouml;schen"><i class="fa fa-times"></i></a>
                                            <a href="../admin/editmission.php?do=archive&id={$missions_eintrag.id}" data-toggle="tooltip" title="" class="btn btn-default" data-original-title="Abschlie&szlig;en"><i class="fa fa-check-circle"></i></a>
                                        </div>
                                    </td>
                                </tr>{/foreach}
                            </tbody>

In einer anderen tpl (der header tpl) will ich per javascript die duration time zwischen zwei koordinaten errechnen und dann in der schleife wieder ausgeben. Genau genommen möchte ich die start-koordinaten (in lat und long - hier fest geschrieben) auch per smarty.variable holen und die jeweilige duration time dann wieder ausgeben:

HTML:
<script type="text/javascript">
	
		var origin1 = new google.maps.LatLng(52.898132, 8.433664);
		var destinationA = 'Bremen';
		
		function calculateDistances() {
		  var service = new google.maps.DistanceMatrixService();
		  service.getDistanceMatrix(
			{
			  origins: [origin1],
			  destinations: [destinationA],
			  travelMode: google.maps.TravelMode.DRIVING,
			  unitSystem: google.maps.UnitSystem.METRIC,
			  avoidHighways: false,
			  avoidTolls: false
			}, callback);
		}

		
		function callback(response, status) {
		  if (status != google.maps.DistanceMatrixStatus.OK) {
			alert('Error was: ' + status);
		  } else {
			var origins = response.originAddresses;
			var destinations = response.destinationAddresses;
			var outputDiv = document.getElementById('outputDiv');
			outputDiv.innerHTML = '';
		
			for (var i = 0; i < origins.length; i++) {
			  var results = response.rows[i].elements;
			  for (var j = 0; j < results.length; j++) {
				outputDiv.innerHTML += results[j].duration.text + '<br>';
			  }
			}
		  }
		}
		
		google.maps.event.addDomListener(window, 'load', initialize);
	
    </script>

Der errechnet mir auch die Zeit - nur weiß ich nicht wie ich das hin und her jetzt in die schleife einbaue.

Ich hoffe jemand hat ne Idee. Meine smarty und javascript kentnisse sind für diese herausforderung leider noch nicht gut genug.
 
Nur ein Hinweis: PHP (und damit Smarty) wird auf dem Server ausgeführt, Javascript im Browser also im Client.

Was du machen kannst: Mit PHP (und damit auch mit Smarty) Java-Script-Code erzeugen.

Wenn du jedoch von Java-Script zurück zu PHP willst, dort Berechnungen ausführen und wieder zurück nach JS, benötigst du eine Technologie, die als AJAX bezeichnet wird.

Was du jedoch auch machen kannst: Mit Java-Script neue DOM-Elemente zu erzeugen und diese mit Werten füllen, die dann im Browser angezeigt werden. Dann ist PHP (und damit Smarty) aber aus er Nummer raus.

Was du aber vorhast, also die Berechnung der Zeit in PHP, angetriggert durch ein Ereignis im Browser (also mittels Javascript) lässt sich nach jetzigen Stand meiner Kenntnis nur durch Ajax erreichen.
 
hmm ok verstehe, aber gibt es denn eine möglichkeit das javascript bereits in der php datei zu verarbeiten um dann bereits das js ergebnis an die tpl datei zu übergeben?
 
Naja, es gibt immer eine Möglichkeit, etwas zu tun. Jedoch stellt sich die Frage, wieviel Aufwand du betreiben willst.

Was spricht denn dagegegen, die Zeit-Berechnung sowie die Ausgabe in Java-Script zu machen?
 
Naja ich würde das ja gern aber ich muss die dann ja mehrfach ausfuhren.

Ich habe auf der Seite eine Tabelle. In einer Spalte stehen lat und long Werte (Punkt a) für jede Zeile will ich die Fahrtzeit zu Punkt b berechnen.

Ich würde es per Ajax machen aber damit hab ich leider noch gar keine Erfahrung gemacht.
 
Die Berechnung findet vermutlich über die Google-API statt. Die Ausgbe der Zeit kommt wohin? Hier?

Code:
<div id="outputDiv" ></div>

In der callback-Funktion in deinem JS hast du ja bereits Code drin, der die Inhalte des DOM manipuliert:

Javascript:
                        var outputDiv = document.getElementById('outputDiv');
			outputDiv.innerHTML = '';
		
			for (var i = 0; i < origins.length; i++) {
			  var results = response.rows[i].elements;
			  for (var j = 0; j < results.length; j++) {
				outputDiv.innerHTML += results[j].duration.text + '<br>';
			  }
			}

Wenn du jetzt in deiner HTML-Tabelle die entsprechenden Elemente, die anschließend die Dauer beinhalten sollen, mit einer HTML-ID versiehst, kannst du mittels der callback-Funktion darauf zugreifen. Bspw. so:

Statt dem outputDiv muss dort ein eindeutiger Name rein, der für den jeweiligen Eintrag steht. Wie genau ist dieses $dispatch-Objekt aufgebaut? Gibt es einen Datenanteil, der sowohl in $dispatch als auch im callback vorhanden ist? Dann kannst du diesen Datenanteil in die ID des divs integrieren und dann im callback dir ein Handle darauf holen. Ich bringe mal als Beispiel den Datenanteil "location" (unabhängig davon ob er jetzt teil des $dispatch ist und was da drin steht):

PHP:
                           <tr>
                                    <td class="text-center"><input type="checkbox" id="checkbox1-1" name="checkbox1-1"></td>
                                    <td class="text-center">{$dispatch.id}</td>
                                    <td id=""></td>
                                    <td><a href="http://www.tutorials.de/admin/mission.php?id={$missions_eintrag.id}">{$dispatch.device_id}</a></td>
                                    <td><div id="outputDiv${dispatch.location}" ></div></td>

Javascript:
		function callback(response, status) {
		  if (status != google.maps.DistanceMatrixStatus.OK) {
			alert('Error was: ' + status);
		  } else {
			var origins = response.originAddresses;
			var destinations = response.destinationAddresses;
                        var location = response.location; // Keine Ahnung, ob das existiert, dient nur als Beispiel
			var outputDiv = document.getElementById('outputDiv' + location);
			outputDiv.innerHTML = '';
		
			for (var i = 0; i < origins.length; i++) {
			  var results = response.rows[i].elements;
			  for (var j = 0; j < results.length; j++) {
				outputDiv.innerHTML += results[j].duration.text + '<br>';
			  }
			}
		  }
		}

Im Übrigen verwendest du bereits AJAX (in Form der Google-API).
 
Vielen Dank für die Tipps.

Ich habe eben ein Codebeispiel gefunden indem die maps API in einem PHP Skript statt in einem JS aufgerufen wird. Das hat mir sehr geholfen.

Werde meinen Code gleich mal hier Posten.
 
Also hier meine Google Maps API Abfrage in der PHP Datei:
PHP:
...
// get all dispatches
    $getDispatches = $db->query("SELECT * FROM eos_dispatches WHERE mission_id = ". $_GET['mission_id'] ." ORDER BY ID ASC") or SQLError();
    while($dispatch = $getDispatches->fetch_assoc()) {
         			
			$getDevices = $db->query(sprintf("SELECT * FROM eos_devices WHERE id = %s", Secure($dispatch["device_id"], 'int') )) or SQLError();
			while($row_devices = $getDevices->fetch_assoc()) {
         		$dispatch["user_id"] = $row_devices["user_id"];
				$dispatch["device_name"] = $row_devices["name"];
			}
			
			$getUsers = $db->query(sprintf("SELECT * FROM eos_users WHERE id = %s", Secure($dispatch["user_id"], 'int') )) or SQLError();
			while($row_users = $getUsers->fetch_assoc()) {
         		$dispatch["user_name"] = $row_users["name"];
			}
			
			// calculate duration
			$from = "". $dispatch["lat"] .", ". $dispatch["long"] ."";
			$to = "Gruppenbührener Straße, Ganderkesee";
			
			$from = urlencode($from);
			$to = urlencode($to);
			
			$data = file_get_contents("http://maps.googleapis.com/maps/api/distancematrix/json?origins=$from&destinations=$to&language=de-DE&sensor=false");
			$data = json_decode($data);
			
			$time = 0;
			$zeit = 0;
			$distance = 0;
			
			foreach($data->rows[0]->elements as $road) {
				$time += $road->duration->value;
				$zeit = $road->duration->text;
				$distance += $road->distance->value;
				
			}
			
			$dispatch["duration"] = $zeit;
		 
		 	$dispatches[] = $dispatch;
    }
	$smarty->assign('dispatchesNum', $getDispatches->num_rows);
    $smarty->assign('dispatches', $dispatches);
	$smarty->assign('missions', $missions);
...

die $dispatch["duration"] kann ich dann in der tpl ausgeben
 
Zurück