Display posts on Google map in radius by latitude and longitude with ACF

The problem:

If you create some new posts with integrated google map using ACF, there is no way to make WP_Query to search posts within some latitude and longitude range.
Problem is that data saved by ACF is like this example:

Array
(
    [address] => Leicester, United Kingdom
    [lat] => 52.6368778
    [lng] => -1.1397591999999577
)

Since entire data is saved as a single post meta value it is impossible to do search between two values.
Second problem I came up to is, if I save data manually into two post meta fields eg: lat_field, lng_field, you cannot get correct posts with WP Query.
The reason for this I believe is because postmeta table value field is of type ‘Longtext’.
Even if I try to do query as ‘Decimal’ field, it still returns wrong results.

The solution

Because of this, I came up with solution by creating custom table where I store lat/lng in correct database column type.
Following steps are required to make this possible:

  1. Create custom database table, with 3 columns: post_id, lat, lng
  2. Create helper functions to easily insert/update/delete data in custom table
  3. Update data in custom table on every post save or edit
  4. Make custom SQL query to retrieve posts
  5. Display posts in standard WP Loop

Let’s get to work

First of all, initial setup is to have Advanced Custom Fields plugin, and create new ‘Google map’ field for your post type you wish to geo locate.

1. Create new database table

/**
 * Create Database table for geodata
 */
global $my_db_version;
$my_db_version = '1.1';

function my_install() {
	global $wpdb;
	global $my_db_version;

	$table_name = $wpdb->prefix . 'my_geodata';

	/*
	 * We'll set the default character set and collation for this table.
	 * If we don't do this, some characters could end up being converted
	 * to just ?'s when saved in our table.
	 */
	$charset_collate = '';

	if ( ! empty( $wpdb->charset ) ) {
	  $charset_collate = "DEFAULT CHARACTER SET {$wpdb->charset}";
	}

	if ( ! empty( $wpdb->collate ) ) {
	  $charset_collate .= " COLLATE {$wpdb->collate}";
	}

	$sql = "CREATE TABLE $table_name (
		id mediumint(9) NOT NULL AUTO_INCREMENT,
		post_id BIGINT NULL UNIQUE,
		lat DECIMAL(9,6) NULL,
		lng DECIMAL(9,6) NULL,
		UNIQUE KEY id (id)
	) $charset_collate;";

	require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
	dbDelta( $sql );

	add_option( 'my_db_version', $my_db_version );
}

function my_geodata_update_db_check() {
    global $my_db_version;
    if ( get_site_option( 'my_db_version' ) != $my_db_version ) {
        my_install();
    }
}
add_action( 'init', 'my_geodata_update_db_check' );

2. Helper functions

These are helper functions that will make it easy to insert/update/delete data into custom database table we created above

/**
 * Insert geodata into table
 */
function insert_geodata( $data ) {
	global $wpdb;

	$table_name = $wpdb->prefix . 'my_geodata';

	//Check date validity
	if( !is_float($data['lat']) || !is_float($data['lng']) || !is_int($data['post_id']) )
    return 0;

	$wpdb->insert(
		$table_name,
		array(
			'post_id' => $data['post_id'],
			'lat'     => $data['lat'],
			'lng'     => $data['lng'],
		),
		array(
			'%d',
			'%f',
			'%f'
		)
	);
}

/**
 * Checks if entry for post_id exists
 */
function check_geodata($post_id) {

	global $wpdb;
	$table_name = $wpdb->prefix . 'my_geodata';

	//Check date validity
	if( !is_int($post_id) )
    return 0;

  $sql = "SELECT * FROM $table_name WHERE post_id = $post_id";
  $geodata = $wpdb->get_row($sql);

  if($geodata) {
  	return true;
  }
}


/**
 * Delete entry for post_id
 */
function delete_geodata($post_id) {

	global $wpdb;
	$table_name = $wpdb->prefix . 'my_geodata';

	//Check date validity
	if( !is_int($post_id) )
    return 0;

  $delete = $wpdb->delete( $table_name, array( 'post_id' => $post_id ) );

  return $delete;
}


/**
 * Update existing
 */
function update_geodata($data) {

	global $wpdb;

	$table_name = $wpdb->prefix . 'my_geodata';

	//Check date validity
	if( !is_float($data['lat']) || !is_float($data['lng']) || !is_int($data['post_id']) )
    return 0;

	$wpdb->update(
		$table_name,
		array(
			'lat'     => $data['lat'],
			'lng'     => $data['lng'],
		),
		array(
			'post_id' => $data['post_id'],
		),
		array(
			'%f',
			'%f'
		)
	);
}



/**
 * Insert or update current post geodata
 */
function add_geodata( $data ) {
	global $wpdb;

	//Check date validity
	if( !is_float($data['lat']) || !is_float($data['lng']) || !is_int($data['post_id']) )
    return 0;

  /**
   * Check if geodata exists and update if exists else insert
   */
  if( check_geodata( $data['post_id'] ) ) {
  	update_geodata( $data );
  } else {
  	insert_geodata( $data );
  }
}

3. Update data in custom table on every post save or edit

To update data in custom table I have decided to create custom function.
This is standard WP Query that will get all posts, then loop trough and save required data into custom table.

To make this little bit more optimised I will use WP Transient and run check every one hour.
Transient will also be deleted on every post edit/save so it will update data every time you edit or create new post.
I have decided to do it like this because to access post meta created by ACF you need to use field ID instead of field name you selected.

/**
 * Loop trough all clinics and update geodata in custom table
 */
function update_post_geodata() {
	$args = array(
		'posts_per_page' => -1,
		'post_type'      => 'post',
	);
  $posts = get_posts( $args );

  if($posts):
    foreach($posts as $item):

    	$tables  = get_field('tables', $item->ID);
        $address = get_field('address', $item->ID);

      /**
       * Update Lat/Lng for every clinic
       */
    	$id  = (int) $item->ID;
    	$lat = (float) $address['lat'];
    	$lng = (float) $address['lng'];

    	if( $address ):
	    	$data = array(
					'post_id' => $id,
					'lat'     => $lat,
					'lng'     => $lng
	    		);

	    	add_geodata( $data );
	    endif;

    endforeach;
  endif;

}

Create Transient

As mentioned above, I have created Transient that runs every hour and executes our function for updating data in custom table.
Also, I delete this transient on every post edit/save, so first refresh of page after that will again execute function.

/**
 * Transient for locations
 * Run update post geodata every hour
 */
if ( false === ( $update_geodata = get_transient( 'locations_update_geodata' ) ) ) {
	update_post_geodata();
  set_transient( 'locations_update_geodata', $update_geodata, 1 * HOUR_IN_SECONDS );
}

// Create a simple function to delete our transient
function delete_transient() {
  delete_transient( 'locations_update_geodata' );
}
// Add the function to the edit/save post hook so it runs when posts are edited
add_action( 'save_post', 'delete_transient' );
add_action( 'edit_post', 'delete_transient' );

Find your lat/lng radius

Next thing we will need is to calculate radius from desired location.
To use that I have found helpful function on stackoverflow (where eles?).

function bar_get_nearby( $lat, $lng, $limit = 50, $distance = 50, $unit = 'mi' ) {
// radius of earth; @note: the earth is not perfectly spherical, but this is considered the 'mean radius'
if( $unit == 'km' ) { $radius = 6371.009; }
elseif ( $unit == 'mi' ) { $radius = 3958.761; }

// latitude boundaries
$maxLat = ( float ) $lat + rad2deg( $distance / $radius );
$minLat = ( float ) $lat - rad2deg( $distance / $radius );

// longitude boundaries (longitude gets smaller when latitude increases)
$maxLng = ( ( float ) $lng + rad2deg( $distance / $radius) ) /  cos( deg2rad( ( float ) $lat ) );
$minLng = ( ( float ) $lng - rad2deg( $distance / $radius) ) /  cos( deg2rad( ( float ) $lat ) );

$max_min_values = array(
'max_latitude' => $maxLat,
'min_latitude' => $minLat,
'max_longitude' => $maxLng,
'min_longitude' => $minLng
);

return $max_min_values;
}

This function will return min/max values for latitude and longitude, and these are the values in between we will do search.

Custom SQL Query

This code goes into page template file, where we want to display our results.
Comments are inline, be sure to check them.

global $wpdb, $paged, $max_num_pages;

/**
 * Get current paged value, for pagination
 */
if ( get_query_var('paged') ) {
   $paged = get_query_var('paged');
} else if ( get_query_var('page') ) {
   $paged = get_query_var('page');
} else {
   $paged = 1;
}

/*
 * Get option from settings, how many posts per page to display
 */
$post_per_page = get_option( 'posts_per_page' );

/*
 * Calculate offset for pagination
 */
$offset        = ($paged - 1)*$post_per_page;

/*
 * Define variables
 */
$sort        = 'ASC'; // Sort posts
$range       = 10; // Range within x miles, default is 10
$search_lat  = false; // Latitude
$search_lng  = false; // Longitude
$table_name  = $wpdb->prefix . 'my_geodata';

Simple SQL query

Create simple sql query that will retrieve all posts, and then if latitude and longitude are set expand the query to search within range.
Simple query will return all results if no latitude/longitude is specified.
Comments on code are inline.

/*
 * Construct basic SQL query
 * Query will return all posts sorted by post title
 */
$sql_query  = "SELECT SQL_CALC_FOUND_ROWS * FROM $wpdb->posts";
$sql_join   = " INNER JOIN $table_name AS geo ON ($wpdb->posts.ID = geo.post_id)";
$sql_where  = " WHERE ($wpdb->posts.post_status = 'publish' AND $wpdb->posts.post_type = 'post')";
$sql_group  = " GROUP BY {$wpdb->posts}.ID";
$sql_order  = " ORDER BY $wpdb->posts.post_title $sort";
$sql_limit  = " LIMIT $offset, $post_per_page";

/*
 * If latitude and longitude are defined expand the SQL query
 */
if( $search_lat && $search_lng ) {
	/*
	 * Calculate range
         * Function will return minimum and maximum latitude and longitude
	 */
	$minmax = bar_get_nearby( $search_lat, $search_lng, 0, $range );

        /*
         * Update SQL query
         */
	$sql_where .= " AND ( ( (geo.lat BETWEEN '$minmax[min_latitude]' AND '$minmax[max_latitude]') AND (geo.lng BETWEEN '$minmax[min_longitude]' AND '$minmax[max_longitude]') ) OR ( terms.term_taxonomy_id = '$search_id') OR ( parent.parent = '$search_id') )";
}

/*
 * Construct SQL query and get results
 */
$sql   = $sql_query . $sql_join . $sql_where . $sql_group . $sql_order . $sql_limit;
$query = $wpdb->get_results($sql, OBJECT);

Standard WP loop

After query is run, we can do standard WP loop, loop trough posts and display them on page

/*
 * Calculate pagination
 */
$sql_posts_total = $wpdb->get_var( "SELECT FOUND_ROWS();" );
$max_num_pages   = ceil($sql_posts_total / $post_per_page);

if ( $query ):

	/**
	 * Loop trough posts
	 */
	global $post;

	foreach ($query as $post):
		setup_postdata($post);
		the_title();
		the_excerpt();
		echo '<hr>';
	endforeach;

/**
 * No results
 */
else: ?>
	<h2>No Posts Found</h2>
<?php endif;
	wp_reset_postdata(); ?>

Conclusion

That’s all folks, you have done it.
I have cut down the markup and tried to make it as less code as possible but again to keep all relevant things in place.
Hope you find this post helpful, if you have any questions, well you know what comments are used for…

55 Comments

  1. Hi! This looks like something I could really use! However my setting is slightly different. I’ve stored long and lat values with ACF without the google maps field. The thing I need is that when a user searches for a ZIP code or city, posts get listed within a certain range. Is this possible with this script? If so, could you help me to steer me into the right direction?

    I’d really appreciate your help!

  2. Hi!Sorry for my bad English! I think that this tutorial is soo good and soo clear. But i don’t understand a “little” thing: where i must copy the code that you write in this tutorial (which file = function.php ?).
    Thanks

  3. Just thought I would share a quick note – the function that Bobz pulled from Stackoverflow is actually a little off and won’t calculate the radius correctly. It’s noted a couple responses under the link to Stackoverflow that Bobz posted, but the correct function is:

    function bar_get_nearby( $lat, $lng, $limit = 50, $distance = 50, $unit = ‘mi’ ) {
    // radius of earth; @note: the earth is not perfectly spherical, but this is considered the ‘mean radius’
    if( $unit == ‘km’ ) { $radius = 6371.009; }
    elseif ( $unit == ‘mi’ ) { $radius = 3958.761; }

    // latitude boundaries
    $maxLat = ( float ) $lat + rad2deg( $distance / $radius );
    $minLat = ( float ) $lat – rad2deg( $distance / $radius );

    // longitude boundaries (longitude gets smaller when latitude increases)
    $maxLng = ( float ) $lng + rad2deg( $distance / $radius) / cos( deg2rad( ( float ) $lat ) );
    $minLng = ( float ) $lng – rad2deg( $distance / $radius) / cos( deg2rad( ( float ) $lat ) );

    $max_min_values = array(
    ‘max_latitude’ => $maxLat,
    ‘min_latitude’ => $minLat,
    ‘max_longitude’ => $maxLng,
    ‘min_longitude’ => $minLng
    );

    return $max_min_values;
    }

    GREAT, AWESOME post Bobz, saved me hours if not days as well. THANK YOU!

  4. Hello Bobz,
    thanks a lot for your work, seems to be exactly what i am looking for. But unfortunately i dont know where to put this code in. How can i use this code to create a new database table for example? Could you send me the whole package as a zip file?

    Best regards,
    Uwe

  5. Hi Bobz,
    Once again, thanks for all the great work with this.

    Quick question – have you ever come across the need to return the results ordered by closest location. I’ve been trying to figure out a way to accomplish this and been a bit stuck.

    1. I just used this and updated the line where $sql_query and $sql_order variables are defined with the code below

      $sql_query = “SELECT SQL_CALC_FOUND_ROWS *, 3956 * 2 * ASIN(SQRT(POWER(SIN(($search_lat – abs(geo.lat)) * pi()/180 / 2),2) + COS($search_lat * pi()/180 ) * COS( abs(geo.lat) * pi()/180) * POWER(SIN(($search_lng – geo.lng) * pi()/180 / 2), 2) )) as distance FROM $wpdb->posts”;

      $sql_order = ” ORDER BY distance, $wpdb->posts.post_title $sort”;

  6. Hello,
    I get a:
    Cannot redeclare delete_transient() (previously declared in /var/www/vhosts/xxx/wp-includes/option.php:547) in /var/www/vhosts/xxxt/wp-content/themes/aust/inc/maps.php on line 219

    Is tehre any adivce on this?
    Thanks!
    P.

    1. You are right! But I don’t understand why there is nobody here with the same error, because In options.php (which is a WP core file) since WP 2.8 a function with the name “delete_transient” exists. Perhaps a PHP version issue ?

  7. Hello, these set of functions work great. I’m running into an issue where I try and place all of this inside of functions.php, so I can retreive the users geolocation, then send that latitude and longitude using WordPress ajax method and it seems to be failing inside of functions.php at the line: $query = $wpdb->get_results($sql, OBJECT);

    I know you included it on the page with the functions.php returning the $sql- that works just fine for me. However when the user on my page clicks a button which gets their geolocation, sends that value via ajax it seems that get_results is returning an empty object. Thanks for any help that you might provide in advance.

    David

    1. Hey Bobz, thanks for the reply! It’s not the case- I’ve declared the global variable, even flushed it, but it doesn’t seem to fix the problem. In your example you use the function get_results() in the template- this shouldn’t be a problem inside of functions.php where wpdb can just as easily be accessed.

      Where I think this might be failing is the sql- I pass the search_lat and search_lng via WordPress ajax method, and I think something about the sql script fails in get_results. Also, you have a varialble in that sql script called search_id- I wanted to omit that line about the OR ( terms.term_taxonomy_id = ‘$search_id’) OR ( parent.parent = ‘$search_id’) and wonder if that would help at all.

      Thanks,
      David

    2. Hi David, it would be best if you print_r your $sql and then run the query alone to see what you get.
      Thing is i’m looking up the ‘posts’ in the same category.

      Check the comment by CN below to see some update about function.

    3. Thanks for pointing me in the right direction Bobz. Here’s my snippet- I ran this in my template page and its returning a blank page minus the header. Im pretty sure something in this script is breaking. I have modified a the post_type and I’ve added lat and longitude for a search where I know it should return at least one result. Does anything look funky to you in this sql script? Thanks again.

      get_results($sql, OBJECT);

      print “”;
      print_r($query);
      print “”;
      ?>

    4. Ok Im getting somewhere, I got it to print out an error, it says: WordPress database error: [Unknown column ‘terms.term_taxonomy_id’ in ‘where clause’]. I don’t have a table named terms. I do have a table, with my prefix of course called dev_term_taxonomy, and inside it I have a column called term_taxomomy_id. Inside of my terms table I also have no such column of term_taxonomy_id. I’m still unsure what this part of the script is doing and why it’s necessary. I’d really appreciate your advisement.

      David

    5. Hi David,

      Looks like a mine mistake in the example provided, you shoud use $wpdb->terms.term_taxonomy_id.
      It is getting posts for a specific term only, so if you are looking for example for taxonomy ‘Shops’ and term ‘Sportware’, meaning you want to get only shops that sell sport clothing.
      If you don’t need this kind of filtering and you want to get all posts within coordinates you can ommit the taxonomy filtering part.

      And a note, you should alwasy have debug mode off and you should always print_r what you get as result and you should always test your sql in some sql app.
      After you get desired result in sql app, then it’s easy to turn that into working function.
      And regarding the error you sent, take care of your quotes and double quotes in sql by escaping where needed.

      BR
      Vlado

  8. Hi Bobz,

    Thank you for posting this, it’s saved me a lot of time having to come up with this myself. I’m just having one small problem where the filtering doesn’t seem to be working if I pass a Lat & Lng into the define variables section. I have it pulling back all the posts from my custom post type (which is cinemas), I just need it to filter so that I can use a search function to dynamically update those fields at the next stage.

    /*
    * Define variables
    */
    $sort = ‘ASC’; // Sort posts
    $range = 300; // Range within x miles, default is 10
    $search_lat = 55.958154; // Latitude
    $search_lng = -3.188905; // Longitude
    $table_name = $wpdb->prefix . ‘my_geodata’;

    1. Hi Jason,

      It’s been a long time from the post, but as far I remember, if I save lat/lng into postmeta table, then the search doesn’t work. I have spent some time testing that and it turned out it’s because of data type, and I was not able to make it work with CAST.

      This is why I decided to create custom table for storing lat/lng values with proper data types for both columns.
      Secondly, to populate that column I hooked into ‘save_post’ / ‘edit_post’ so I can create/update data in custom table every time post is created or edited.

      Basically this is what’s going on in my article.

      Secondly regarding your issue, it’s difficult for me to say what might be wrong.
      I would recommend to test your query in some sql app (like sequel / phpmyadmin ) and find the correct syntax for your case.

      hope it helps

      BR
      Vlado

  9. I’d like to post a full bit of code that’s working flawlessly on a few websites i manage. Some websites use Types plugin and other use ACF.
    In Types i set up 2 fields for Lat and Lng, and of course is far more easy, but you know clients are not aware how to extract Lat and Lng from google maps when doing data entry, so i worked a bit and came up with ACF alternative, which on one side is easier to use, especially when adding a map to the Custom Fields, on the other side is harder to extract those values.
    Anyway by googling all around i came up with this code, taking pieces of it here and there. It definitely works, all you have to change is the Custom post type in the args (mine was ‘apartment’), and some other values for the html part for pop up window. Please have a look. Cheers

    //Array of JSON objects.
    var markers = [ -1,
    ‘post_type’ => ‘apartment’,
    ‘orderby’ => ‘rand’
    );

    // query
    $the_query = new WP_Query( $args );

    if( $the_query->have_posts() ):
    $myarray = array();
    while( $the_query->have_posts() ) : $the_query->the_post();
    global $post;
    $location = get_post_meta($post->ID, ‘posizione_mappa’, true); //this will extract the map position array, change posizione_mappa to your ACF gmaps field name
    $mylat = $location[‘lat’]; //this wil fetch for previous array only Latitude value
    $mylng = $location[‘lng’]; //this wil fetch for previous array only Longitude value
    $mytitle = get_post_meta ($post->ID, ‘citta’, true); //change citta to your field name
    $myaddress = get_post_meta($post->ID, ‘wpcf-tipologia’, true); //change wpcf-tipologia to your field name
    $post_thumbnail_id = get_post_thumbnail_id($recent[‘ID’]);
    $post_thumbnail_url = wp_get_attachment_image_src($post_thumbnail_id, ‘medium’ );
    $post_map_image = ”;
    if ( has_post_thumbnail() ) {
    $thumb_id = get_post_thumbnail_id();
    $thumb_url_array = wp_get_attachment_image_src($thumb_id, ‘homepage-tiles’, true);
    $thumb_url = $thumb_url_array[0];
    }
    $data_for_infowindow = ‘‘.$mytitle.’‘.$post_map_image.’‘.$myaddress.”;

    $new_element = ‘{“title”: ”.get_post_meta($post->ID, ‘wpcf-titoloslider’, true).”,
    “lat”: ”.$mylat.”,
    “lng”: ”.$mylng.”,
    “description”: ”.$data_for_infowindow.”}’;
    array_push($myarray, $new_element);
    endwhile;
    echo implode(“,”,$myarray);
    endif;

    wp_reset_query();

    ?>
    ]; //here ends the JSON part
    window.onload = function () {
    LoadMap();
    }
    function LoadMap() {
    var mapOptions = {
    center: new google.maps.LatLng(markers[0].lat, markers[0].lng),
    zoom: 17, // The initial zoom level when your map loads (0-20)
    minZoom: 6, // Minimum zoom level allowed (0-20)
    maxZoom: 20, // Maximum soom level allowed (0-20)
    zoomControl:true, // Set to true if using zoomControlOptions below, or false to remove all zoom controls.
    zoomControlOptions: {
    style:google.maps.ZoomControlStyle.DEFAULT // Change to SMALL to force just the + and – buttons.
    },

    mapTypeId: google.maps.MapTypeId.ROADMAP, // Set the type of Map
    scrollwheel: false, // Disable Mouse Scroll zooming (Essential for responsive sites!)
    // All of the below are set to true by default, so simply remove if set to true:
    panControl:false, // Set to false to disable
    mapTypeControl:false, // Disable Map/Satellite switch
    scaleControl:false, // Set to false to hide scale
    streetViewControl:false, // Set to disable to hide street view
    overviewMapControl:false, // Set to false to remove overview control
    rotateControl:false // Set to false to disable rotate control
    };
    var infoWindow = new google.maps.InfoWindow();
    var latlngbounds = new google.maps.LatLngBounds();
    var map = new google.maps.Map(document.getElementById(“dvMap”), mapOptions);

    for (var i = 0; i < markers.length; i++) {
    var data = markers[i]
    var myLatlng = new google.maps.LatLng(data.lat, data.lng);
    var marker = new google.maps.Marker({
    position: myLatlng,
    map: map,
    title: data.title
    });
    (function (marker, data) {
    google.maps.event.addListener(marker, "click", function (e) {
    infoWindow.setContent("” + data.description + “”);
    infoWindow.open(map, marker);
    });
    })(marker, data);
    latlngbounds.extend(marker.position);
    }
    var bounds = new google.maps.LatLngBounds();
    map.setCenter(latlngbounds.getCenter());
    map.fitBounds(latlngbounds);
    }

    1. i noticed that a large amount of code has been cut out, how can i still post it in full version?
      thanks

    2. Hi, would you mind using pastebin or similar for sharing large portion of code please.

      I did not understood your first comment well, you have some question regarding post, or you share some example solution?

  10. Hi thanks very much!

    I had to change two lines in the bar_get_nearby function to make it work for me.

    $maxLng = ( float ) $lng + rad2deg( $distance / $radius) / cos( deg2rad( ( float ) $lat ) );
    $minLng = ( float ) $lng – rad2deg( $distance / $radius) / cos( deg2rad( ( float ) $lat ) );

  11. This solution looks brilliant and is something I definitely need. Im just having some problems with it. I am getting this error on the page:
    WordPress database error: [Table ‘fadc.wp_my_geodata’ doesn’t exist]
    SELECT SQL_CALC_FOUND_ROWS * FROM wp_posts INNER JOIN wp_my_geodata AS geo ON (wp_posts.ID = geo.post_id) WHERE (wp_posts.post_status = ‘publish’ AND wp_posts.post_type = ‘post’) GROUP BY wp_posts.ID ORDER BY wp_posts.post_title ASC LIMIT 0, 10
    And in my browser console it is giving me a “Uncaught SyntaxError: Unexpected indentifier” which it says is on line 4 which is this: global $my_db_version;
    Any help would be appreciated. Thank you!

  12. Still works in Feb 2018! However, first of all, a very big thanks for compiling this so thoroughly! It has been a very, very, very amazing help!

    For those not sure where to add the code -> functions.php

    Adjustments I had to make:
    1. For “3. Update data in custom table on every post save or edit” -> change ‘posts’ to your post type
    2. For “Create Transient” -> Rename the delete_transient function (and the actions), otherwise, it will throw a fatal error because this function has been declared already.
    3. For “Simple SQL Query” -> Change AND $wpdb->posts.post_type = ‘post’)”; to your post type
    4. Also for the “Simple SQL Query” section, remove the following from the ‘where’ clause when lat/lng has been set:
    “OR ( terms.term_taxonomy_id = ‘$search_id’) OR ( parent.parent = ‘$search_id’)”
    5. Change the radius calculation within the bar_get_nearby function for the longitude as following:

    $maxLng = ( float ) $lng + rad2deg( $distance / $radius) / cos( deg2rad( ( float ) $lat ) );
    $minLng = ( float ) $lng – rad2deg( $distance / $radius) / cos( deg2rad( ( float ) $lat ) );

    Apart from that, it works perfectly fine! Thanks again.

  13. I think the longitude calculations are wrong.

    Here’s the corrected code:

            $maxLng = (float) $lng + (rad2deg($distance / $radius)  / cos(deg2rad((float) $lat)));
            $minLng = (float) $lng - (rad2deg($distance / $radius)  / cos(deg2rad((float) $lat)));
    
  14. Hi, thank you for your post!

    I have a question

    How I can join this new table to postmeta table, becouse I have a custom search, and three parameters by search – custom category taxonomy, custom tag taxonomy and ACF google map field

    And I search by WP_query, and at this moment I dont have my new parameters from new table at WP_query

    This my table http://prntscr.com/k8rhpj
    And this http://prntscr.com/k8ri02 – postmeta table

    Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *