PHP Version 7.4
I am currently working on a small php program to take certain shipments and optimize the order of them to the most efficient route. So far so good, it works with the google maps api the following way:
$url = "https://maps.googleapis.com/maps/api/directions/json?"; $url .= "origin=".urlencode($this->startPoint); $url .= "&destination=".urlencode($this->endPoint); $url .= "&waypoints=".urlencode("optimize:true")."|"; $x = 0; foreach($ordersadress as $order){ if($x != 0){ $url .= urlencode("|"); } $url .= urlencode($order["address"]); $x++; } $url .= "&key=".$conf->global->GOOGLE_MAPS_API_KEY; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $resp = curl_exec($ch); $json = json_decode($resp);
Now, in order to know which Shipment actually comes first, I go through the json response and compare the addresses of my shipments to each waypoint in the response to see which address comes first and so on. Here is my problem, in the response the addresses are not written out, they are shortened. For example with a german address, my shipment address that I add to the api call is “Kirchenplatz 4”. In googles response they shorten it to “Kirchenpl. 4”. I think the equivalent in english would be changing “Road” to “Rd”. (I will put an example request at the end, incase you do not know what it looks like, you do need a Google API key though.)
For now, I’m doing it the following way:
foreach($json->routes[0]->legs as $leg){ if($iterator != 0){ foreach($ordersadress as $order){ $addy = explode(",", $leg->start_address); $oa = explode(",", $order["address"]); //Here I compare if the returned address is the same as the one on the shipment, needs to be a 1:1 match, this is my issue if(strpos($oa[0], $addy[0]) !== false){ $lat = $leg->start_location->lat; $lon = $leg->start_location->lng; $co = $order["object"]; $this->orders[] = ["rowid" => $co->id, "sortorder" => $sortnum, "notes" => "", "tourdate" => $tourdate->format("d.m.Y"), "address" => $leg->start_address, "drivetime" => $leg->duration->value, "object" => $co, "lat" => $lat, "lon" => $lon]; $this->kmAll += round($leg->distance->value/1000, 2); $sortnum++; foreach($leg->steps as $step){ $polyline .= $step->polyline->points; } break; } } unset($order); }
This example only works with exact 1:1 matches, which is ofcourse not viable in a real world scenario, as the workers of my customer will not be able to always put the address in the exact same way that google returns it, besides, there is already data for thousands of shipments which would have to be changed.
I have thought of following solutions:
Get a list of all words that are shortened by google, and then do it to my addresses. However I was not able to find a list.
My second solution was to do a percentage match of 2 addresses, and the one with the highest match would be at the position that google returned. With this solution, I am going to be honest I did not really understand the similar_text
function and how it works and I am not sure if it would even be a good solution in my case.
I am open to any ideas and suggestions that you might have.
Example Google API request:
https://maps.googleapis.com/maps/api/directions/json?origin=Lange+G.+20%2C+2700+Wiener+Neustadt&destination=Ruckergasse+42%2C+1120+Wien&waypoints=optimize%3Atrue|Brauhausgasse+6%7CHauptpl.+1%2C+Graz%7CKirchenpl.+4%2C+G%C3%A4nserndorf%7CS%C3%BCdtiroler+Pl.+1%2C+Salzburg%7CUnter+dem+Rucker+14%7CVivenotgasse+3%2F6+13%2C+Wien&key=YOUR_API_KEY
Advertisement
Answer
After trying for a while and asking some friends I arrived at the solution of using the fuzzy logic to match addresses. Luckily there is already an implementation of a method of this logic which is called levenshtein($string1, $string2)
I would suggest reading it up here: https://www.php.net/manual/de/function.levenshtein.php
Example 1 was basically my solution to the problem and has been working without problems so far. However be careful! As explained here in the comment below example 1 using UTF-8 will cause problems!