0

I have created location proximity functionality. I have a WP_Query loop created for a custom post type called Instructor. Each instructor has an address, so if someone enters a zip code it calculates the distance using Google's API for each custom instructor post. It successfully calculates the distance for each post, but its dynamic data is not saved in the database.

I created another wp_query loop before the main one just to get the list, so I have a data like this:

$result = array (
 '223' => '1.99'
 '136'  =>  '1.82',
 '166' => '1.93',
);

where key is post id and value is distance. Is there any way I can show the nearest instructor based on the data from query that is made before actual one?

2
  • can you reword the section about WP query is instructor? It doesn't make sense in english
    – Tom J Nowell
    Commented Mar 30, 2020 at 16:37
  • @TomJNowell Sorry I meant WP_Query pulls out custom post type named instructor .
    – user145078
    Commented Mar 30, 2020 at 16:44

1 Answer 1

0

Update: The User has clarified the request in the comment to my answer, so i add some info above my original answer. The original answer is still valid ;)

To use external data for your "main" query, you can use the pre_get_posts hook.

Use it like this:

add_action('pre_get_posts','get_radius_instructors_for_my_posts');

function get_radius_instructors_for_my_posts($query){
    if($query->is_main_query() && !is_admin()){
        if($query->is_search()){
             //use your function to get the post ids that are in radius
             $post_ids = do_whatever_to_get_the_post_ids();
             $query->set('post__in',$post_ids);
             $query->set('orderby','post__in');
        }
    }
}

Do you mean that you use the Google Maps Geocoding Service to Geocode the instructors addresses on every pageload? That is not a wise thing to do because of two reasons: 1) Performance. If you have to geocode every address every search, that would very slow. 2) Cost. Googles APIs are only free below a specific use each month.

The better way would be to geocode the instructors addresses on Post Type Save, save the latitude and longitude in the database, and on searching for zip use the Geocoding Feature for the zip to make a custom query based on the latitude and longitude of the searcher.

As i don't know how exactly you save the addresses, i can't help you there. But i can give you a function to get the posts that are in a specific radius from your users location: (this presumes that your post type key is "instructor" and the latitude and longitude of their addresses are stored in post meta keys "lat" and "lng")

function get_posts_in_radius($center_lat,$center_lng,$radius_in_km=50){
    $multiplier=3959; //miles
    $multiplier=($multiplier*1.609344); //use km instead
    $sql = $wpdb->prepare("SELECT $wpdb->posts.ID, pm1.post_id, pm1.meta_value AS lat, 
                                pm2.meta_value AS lng,
                                (%f * ACOS( COS( RADIANS(%f) ) * COS( RADIANS( pm1.meta_value  ) ) * COS( RADIANS(  pm2.meta_value ) - RADIANS(%f) ) + SIN( RADIANS(%f) ) * SIN( RADIANS( pm1.meta_value ) ) ) ) AS distance
                        FROM $wpdb->posts 
                            INNER JOIN $wpdb->postmeta pm1
                                ON $wpdb->posts.ID = pm1.post_id
                                INNER JOIN $wpdb->postmeta pm2 
                                    ON pm1.post_id = pm2.post_id 
                                        AND pm1.meta_key = 'lat' 
                                        AND pm2.meta_key = 'lng' 
                        WHERE $wpdb->posts.post_status = 'publish' AND $wpdb->posts.post_type = 'instructor' HAVING distance < %d ORDER BY distance ASC",$multiplier,$center_lat,$center_lng,$center_lat,$radius_in_km);
    $response = array();
    if($rows = $wpdb->get_results($sql,ARRAY_A)){
        foreach($rows as $row){
            $response[] = array(
                                'id' => $row['post_id'],
                                'title' => get_the_title($row['post_id']),
                                'lat' => $row['lat'],
                                'lng' => $row['lng'],
                                'distance' => $row['distance']
                          );
        }
    }
    return $response;
}

Happy Coding!

1
  • Thanks for the answer. Actually I use metabox to set the instructor location. Now the user enters his zip code in field provided. It calculates the distance from each instructor and show it. Now problem is, there is no ordering, which is where i am stuck at. So i created another wp_query loop before this one now i have array of post id with distances from each (as is question). Is there is any way to use that data to sort , so it orders in such a way that closest instructor comes first and next ?
    – user145078
    Commented Mar 31, 2020 at 10:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.