I just realized that I cannot call directly on a URL from my AngularJS application due to CORS. Therefore, I expect I will have to use the Javascript API.
The following link provides me with the data I want:
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=' + myPosition.lat + ',' + myPosition.lng + '&rankby=distance&key=' + key + '&sensor=false&type=clothing_store
However, I cannot figure how to achieve the same using the Javascript API. I found this in the documentation, but I do not need a map - just the names and coordinates of the nearby stores.
How can I get a hold of the same data using the Javascript API?
If you've already got a Google Maps for JS API Map Key, you can do a Places query from the server side. Note, however, that you're limited to 1000 queries per day.
You can probably do this directly in your client and avoid CORS issues, but here's how I've done it previously using PHP:
<?php
function ReturnEmpty()
{
// Something's wrong, return an empty set.
echo '{"d":[]}';
}
$q = (isset($_GET["query"])) ? $_GET["query"] : 'NULL';
if( $q == "" )
{
ReturnEmpty();
}
else
{
// I'm showing the "textsearch" option, but there is also a "nearbysearch" option..
$url = "https://maps.googleapis.com/maps/api/place/textsearch/json?query="
. urlencode($q)
. "&key=YOUR_GOOGLE_MAPS_KEY_HERE";
$json = file_get_contents($url);
$data = json_decode($json, true);
echo $data;
}
?>
You can use the nearbySearch(request, callback) method on google.maps.places.PlacesService(map).
In your case, the request should have a location (that contains the lat and lng) and a radius.
There are code samples here.
Related
I am using Google Autocomplete (under Maps Javascript API) in Angular 5.
For the purpose of my website, I retrieve details of a place, which includes any available photos. For the photos, I will get the photo URL via the getURL() method.
============
What works previously
Previously, I am able to save the url in the database and use that same url to retrieve the photos at a later date. Example of the URLs includes:
https://lh3.googleusercontent.com/p/AF1QipM3QnVu-6W-ZtoTry29MOzDt7vpWzPZAPZbBfqZ=w600-h500-k
https://lh3.googleusercontent.com/p/AF1QipPQ5imb4nzfK1TxG7KAFx2vEx1SoYXeQApA6SVX=w600-h500-k
https://lh4.googleusercontent.com/-l_W16EbIqzk/WS5E5R9_VbI/AAAAAAAAnD8/ajWr1IeY7solMudnxIV21vjqmxLt8CJOACLIB/w300-h250-k
============
Situation now
However, in recent weeks, the same getURL() method returns photos that expire. I have no problem seeing the photo when I first retrieved it. As usual, I save the url to my database. However, after a few days, I am unable to retrieve the same images. Example includes:
https://maps.googleapis.com/maps/api/place/js/PhotoService.GetPhoto?1sCmRaAAAAiEX-USwjAvitgPnxuaW7stCrTkQMxyydpcmlg5IrEWnSUS5D3Z2D9evQ_n41Ght-8dr3cZtjvx4oINIEpqj4Z4fvaCyqv6xF0oPC_lw88P6FUQ7SXP2vElr61Zi568IdEhBWY_7xGFNHvdQyDqxZApR3GhS-IM17Pp8oMGlMK0FrXW310tsPCw&3u2000&4u1000&5m1&2e1&key=AIzaSyAbdivx4G0igYO5yr3vTUJcQF5s8lTdXho&callback=none&token=96678
https://maps.googleapis.com/maps/api/place/js/PhotoService.GetPhoto?1sCmRaAAAAkz5xG6DVQSbwHyBIQIshs2FedNARq6oG0Ea6gUxvljPdnHFJqcJniD0gkd2BZQ7-IPc6FPVlYYb7G0t8K_-8hVYizZl4HGy5V1QiE4sjdWLhyWX7MnJYEA61zoup_fbpEhDWYpcVACyQ6RKsqpyS-bQKGhQw8Tg2O8rcGJfaKI0jW3T7XKAYZg&3u2000&4u1000&5m1&2e1&key=AIzaSyAbdivx4G0igYO5yr3vTUJcQF5s8lTdXho&callback=none&token=20957
https://maps.googleapis.com/maps/api/place/js/PhotoService.GetPhoto?1sCmRaAAAAfLQZlWahAqUSlQA5y7-NTeYLMDim6M1L_ht3_qNCSL4dBeX2VWVdhzuJXeqGcKN30XAv3WZHtY2QUXaoKV5fVGSUld2IdOKfV0bv32kEFUdgMlqou9Ij5YVaJ15mfoVcEhB-6hiiaiPS3349mCZMYOPyGhTrEZUg0XGOuBW1rsrLlpmaO9nvqg&3u2000&4u1000&5m1&2e1&key=AIzaSyAbdivx4G0igYO5yr3vTUJcQF5s8lTdXho&callback=none&token=38662
============
What may be the problem
From the makeup of the URLs, there are obvious differences. The older URLs comes with the googleusercontent as the domain name. While the newer photos end with a token. Right now, I am still able to retrieve the older photos even though i may have added them months ago. For the new photos, it expires after a few days.
I understand that there are solutions that require the use of photo_reference, however, I am unable to find a way to retrieve photo_reference via the javascript API I am using. I have tried to use Places Service method (new google.maps.places.PlacesService) but it returns the same getURL() method which retrieves the same temporary URL as above.
=======================
Thus my question are:
Does anyone know whether the change in url is intended or it may be an error from google? If it is intended, is there any way to get a permanent url that does not expire.
Does anyone know how to retrieve photo_reference via the google javascript API?
Many thanks for your help in advance.
Google says this is intentional behavior and that the only thing users should be “caching” is the “place_id”.
See: https://issuetracker.google.com/issues/110711934
unfortunately, I think to retrieve the photo reference, a separate Place Details request will need to be made using the Place ID.
I worked around this by writing a serverside function to recursively follow the redirect path and get the ultimate photo url. Example in elixir:
def follow(url) when is_binary(url) do
case HTTPoison.get(url) do
{:ok, %HTTPoison.Response{status_code: status_code, headers: headers}} when status_code > 300 and status_code < 400 ->
case get_location_header(headers) do
[url] when is_binary(url) ->
follow(url)
_ ->
{:error, :no_location_header}
end
{:ok, %HTTPoison.Response{status_code: 200}} ->
{:ok, url}
reason ->
{:error, reason}
end
end
defp get_location_header(headers) do
for {key, value} <- headers, String.downcase(key) == "location" do
value
end
end
so now i can take the long
https://maps.googleapis.com/maps/api/place/js/PhotoService.GetPhoto?1sCm... url and run it through follow() which returns the googleusercontent url for the image itself.
i then pass THAT url to filestack to copy and store and serve over CDN...
bit of a crazy workaround, but it finally fixed this issue for us.
Here is a code in which you can pass the temporary URL fetched from Google places service API get photos, and it returns a permanent URL that you store in your database for later use.
<?php
function get_redirect_url($url){
$redirect_url = null;
$url_parts = #parse_url($url);
if (!$url_parts) return false;
if (!isset($url_parts['host'])) return false; //can't process relative URLs
if (!isset($url_parts['path'])) $url_parts['path'] = '/';
$sock = fsockopen($url_parts['host'], (isset($url_parts['port']) ? (int)$url_parts['port'] : 80), $errno, $errstr, 30);
if (!$sock) return false;
$request = "HEAD " . $url_parts['path'] . (isset($url_parts['query']) ? '?'.$url_parts['query'] : '') . " HTTP/1.1\r\n";
$request .= 'Host: ' . $url_parts['host'] . "\r\n";
$request .= "Connection: Close\r\n\r\n";
fwrite($sock, $request);
$response = '';
while(!feof($sock)) $response .= fread($sock, 8192);
fclose($sock);
if (preg_match('/^Location: (.+?)$/m', $response, $matches)){
if ( substr($matches[1], 0, 1) == "/" )
return $url_parts['scheme'] . "://" . $url_parts['host'] . trim($matches[1]);
else
return trim($matches[1]);
} else {
return false;
}
}
function get_all_redirects($url){
$redirects = array();
while ($newurl = get_redirect_url($url)){
if (in_array($newurl, $redirects)){
break;
}
$redirects[] = $newurl;
$url = $newurl;
}
return $redirects;
}
function get_final_url($url){
$redirects = get_all_redirects($url);
if (count($redirects)>0){
return array_pop($redirects);
} else {
return $url;
}
}
echo get_final_url($temporary_google_url);
?>
Source: http://w-shadow.com/blog/2008/07/05/how-to-get-redirect-url-in-php/
I am using Laravel Framwork for my php software and I ran into an issue with localizaing the text within the JaveScript files.
I have a database value that sets the locale of each user.
App::setLocale(Auth::user()->lang) in the Middleware folder. It works as expected on the different blades using either #lang('file.name') or trans('file.name').
For my JavaScript files I am using this method. It works fine, but it seems that it doesn't update the locale based on the value in the middleware, but based on the locale value in config/app.php.
The php pages all work and update according the the database value.
Any idea what I might be missing?
Problem in the link that you provided is that it will get all the translations for current language and it will cache that forever. So even though you are changing languages, /js/lang.js will always return same cached response.
While it is good idea to cache the response of reading all translation files for language, when you create the cache you need to do that per language and to use unique cache key per language (look at the code)
// Localization
Route::get('/js/lang.js', function () {
$minutes = 10;
$lang = App::getLocale();
// each language it will be cached with different key
// example: "en.lang.js", "fr.lang.js", ...
$strings = Cache::remember($lang.'.lang.js', $minutes, function() use ($lang) {
$files = glob(resource_path('lang/' . $lang . '/*.php'));
$strings = [];
foreach ($files as $file) {
$name = basename($file, '.php');
$strings[$name] = require $file;
}
return $strings;
});
return response('window.i18n = ' . json_encode($strings) . ';')
->header('Content-Type', 'text/javascript');
})->name('assets.lang');
Currently,I have created a page showing all the locations of the users (all from MySQL database) on google map. But because there are 5000+ user locations, it takes a long time to load the page.
I would like to make it more efficiently by only querying the user locations within certain area. (the area I am viewing)
What could I do to make it more efficient? Does google maps API support the feature that I want? I heard I can do geofencing mysql, but I cannot really find how to use it.
Thank you in advance.
There are probably many ways to do what you want. If you have the longitude and latitude of the users (which sounds like you do) then instead of loading all user locations (select latitude, longitude from users) then narrow down the location by specifying a range for the coordinates of your user, so your select looks something like this (in pseudo query)
select latitude, longitude from users where latitude between (user.latitude + whateverrangeyouwant and user.latitude - whateverrangeyouwant) AND longitude between (user.longitude + whateverrangeyouwant AND user.longitude - whateverrangeyouwant);
The range can probably be taken from the map.bounds property
You can then send this back to your script using a service that will then remove the markers from the map and add the one ones based on your service response. So your javascript would look something like this (in pseudo code)
get user location;
send service request for user locations and get them back in an array
remove current markers
add new markers from service result
The service in PHP probably look something like this:
$minLat = $_REQUEST['lat'] - ($_REQUEST['dl'] / 2);
$maxLat = $_REQUEST['lat'] + ($_REQUEST['dl'] / 2);
$minLon = $_REQUEST['lon'] - $_REQUEST['dln'];
$maxLon = $_REQUEST['lon'] + $_REQUEST['dln'];
$query = 'SELECT locations.latitude,
locations.longitude
FROM locations
WHERE (latitude BETWEEN ' . $minLat . ' AND ' . $maxLat . ') AND
(longitude BETWEEN ' . $minLon . ' AND ' . $maxLon. ')';
}
$query = DB::query($query);
$json = array();
while($location = $query->fetch_assoc()) {
$json[] = $location;
}
header('Content-Type: application/json');
echo json_encode($json);
exit();
Hope that helps.
i am trying in pull my data from mySQL and convert it to a format I can then pass to google.maps API. I am thinking mySQL -> php -> javascript -> google.maps makes the most sense but am deffinitly open to other suggestions.
So far I have connected to and successfully queried my data into an array
<?php
//library of mysql functions including linkDB()
include('../sqlFunctions/sqlFunctions.php');
//Establish connection to database
if($link = linkDB()){
echo "connected to DB";
}
//set up a MySQL query. I am simply pulling geocoordinate ints, strings and boolean.
$sql = "SELECT title
,lat
,lng
,titleYou
,descriptionAre
,privacyRockstar
FROM shelters;";
if($results = $link->query($sql)){
echo "<p>Query succsessful.</p>";
}else{
echo "Query Failed";
}
//initialize an array to store data
$rows = array();
while ($data = $results->fetch_assoc()) {
$rows[] = $data;
echo "<br><br>Loop rotation: ";
var_dump($data);
}
echo "<br><p>The End of The Loop<p><br>";
var_dump($rows);
?>
Now I just need to convert this data into something usable I can pass to google.maps.
Before I was pulling JSON from a text file, which worked, but I want to flexibility and stability of a database. It was easy to parse into and array of Javascript Objects. Then I could just call the index and the property that I needed as you can see from this function I was using.
function setMarkers(){
for(i=0; i < jsonParsed.arrayOfObjs.length; i++){
//setting parameters to hand to google
var markerOptions = {
position : jsonParsed.arrayOfObjs[i].position,
map : mapCanvas,
description : jsonParsed.arrayOfObjs[i].title,
icon: 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png',
};
//create marker
this ['marker' + i] = new google.maps.Marker(markerOptions);
}
}
Thank you for any light you can help shed on my issue.
It sounds like you already found your answer but I'll post for completeness.
Simply change your the var_dump($rows) line to json_encode($rows).
Read more about json_encode in the php docs.
You probably want to have two php files:
api.php file that emits Content-type: application/json
index.php file that emits Content-type: text/html and calls api.php
On the index page, you can make an AJAX call to your API endpoint and then use JSON.parse(response).
I'm trying to create a Google Places URL that can be reused and concatenated with a response from my database.. Not getting this to work and have been trying for a couple of days with no luck! If I echo out the both strings, from PHP on to my web page and copy&paste it, both addresses generate the same Google Places result, but when I print the JSON decoded response I get UNKNOW_ERROR from Google..
This is what I have been trying to use. The first and the second $googlePlacesAPI contains the exact same URL, just that one is concatenated and the other is "hard coded".
$googlePlacesAPI = "https://maps.googleapis.com/maps/api/place/textsearch/json?query=" .
$BarName. "+" . $BarCity . "&sensor=false&types=bar|night_club&key=" . $mySuperSecretKey;
$googlePlacesAPI = "https://maps.googleapis.com/maps/api/place/textsearch/json?query=" .
$BarName. "+" ."Göteborg". "&sensor=false&types=bar|night_club&key=" . $mySuperSecretKey;
To get the value of $BarCity I use this piece of code (before creating the $googlePlacesAPI variable):
$row = mysqli_fetch_array(mysqli_query($con, "SELECT * FROM City WHERE ID = $CityID"));
mysqli_close($con);
$BarCity = $row['CityName'];
EDIT:
This is how I decode the answer:
$placesSearch = json_decode(file_get_contents($googlePlacesAPI));
You probably want to close the connection after you're done with $row:
$row = mysqli_fetch_array(mysqli_query($con, "SELECT * FROM City WHERE ID = $CityID"));
$BarCity = $row['CityName'];
mysqli_close($con);
See a sample of mysqli_fetch_array usage at http://nl3.php.net/mysqli_fetch_array#example-1728