Finding all results from database within 500 miles of the given latitude and longitude [closed]

The problem was when I send the query to the database it was changing my array level other than that the ‘s’ value was not going empty due to which it was preventing my records to be fetched and the third and most important one was the way I was making my query by changing my function resolved my problem.

Here is the updated code for this logic in case some one else need to make such functionality.

The main function where all the data is gathering up and making a query

public function pre_get_posts($q) {

    // check if the user is requesting an admin page 
    if (is_admin() || !$q->is_main_query())
        return;

    if (!is_post_type_archive('auto-listing'))
        return;

    if (!is_search())
        return;

    $meta_query = array();

    $year_query[] = $this->year_query();
    $model_query[] = $this->model_query();
    $condition_query[] = $this->condition_query();
    $odometer_query[] = $this->odometer_query();
    $price_query[] = $this->price_meta_query();
    $body_type_query = $this->body_type_query();
    $country_query = $this->country_query();
    $transmission_query = $this->transmission_query();
    $radius_query[] = $this->radius_query($q);

    $query_1 = array_merge($country_query, $year_query, $model_query, $condition_query, $price_query, $odometer_query, $transmission_query);
    // if our radius query fails, fall back to keyword searching
    // will fail with no map API key
    if (empty($radius_query[0]) || !$radius_query[0]) {
        $keyword_query[] = $this->keyword_query($q);
        $query_2 = $keyword_query;
    } else {
        $query_2 = $radius_query;
    }

    // if no keyword
    if (empty($_GET['s'])) {
        $query_1['relation'] = 'AND';
        $meta_query[] = $query_1;
    }

    // if keyword
    if (!empty($_GET['s'])) {
        $query_2['relation'] = 'OR';
        $meta_query[] = $query_1;
        $meta_query[] = $query_2;
        $meta_query['relation'] = 'AND';
    }

    $q->set('meta_query', $meta_query);

    $q->set('tax_query', $body_type_query);

    $q->set('post_type', 'auto-listing');

}

Radius query function that was actually doing the magic

public function radius_query($q) {

    if (isset($_GET['s']) && !empty($_GET['s'])) {

        $searchterm = isset($q->query_vars['s']) ? sanitize_text_field($q->query_vars['s']) : '';

        // we have to remove the "s" parameter from the query, because it will prevent the posts from being found
        $q->query_vars['s'] = '';

        if ($searchterm != '') {

            $search_radius = $this->geocode($searchterm);

            if (!$search_radius)
                return false;

            $lat = $search_radius['lat']; // get the lat of the requested address
            $lng = $search_radius['lng']; // get the lng of the requested address
            // we'll want everything within, say, 30km distance
            $distance = isset($_GET['within']) && !empty($_GET['within']) ? floatval($_GET['within']) : 0.1;

            // earth's radius in km = ~6371
            $radius = auto_listings_metric() == 'yes' ? 6371 : 3950;

            // latitude boundaries
            $maxlat = $lat + rad2deg($distance / $radius);
            $minlat = $lat - rad2deg($distance / $radius);

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

            // build the meta query array
            $radius_array = array(
                'relation' => 'AND',
            );

            $radius_array[] = array(
                'key' => '_al_listing_lat',
                'value' => array($minlat, $maxlat),
                'type' => 'DECIMAL(10,5)',
                'compare' => 'BETWEEN',
            );
            $radius_array[] = array(
                'key' => '_al_listing_lng',
                'value' => array($minlng, $maxlng),
                'type' => 'DECIMAL(10,5)',
                'compare' => 'BETWEEN',
            );

            return apply_filters('auto_listings_search_radius_args', $radius_array);
        }
    }
}

And now the final function that was fetching the lat and long from the zip code that user enters

private function geocode($address) {
    // url encode the address
    $address = urlencode(esc_html($address));

    // google map geocode api url
    $url = auto_listings_google_geocode_maps_url($address);

    $arrContextOptions = array(
        "ssl" => array(
            "verify_peer" => false,
            "verify_peer_name" => false,
        ),
    );

    // get the json response
    $resp_json = file_get_contents($url, false, stream_context_create($arrContextOptions));

    // decode the json
    $resp = json_decode($resp_json, true);

    //pp( $resp );
    // response status will be 'OK', if able to geocode given address 
    if ($resp['status'] == 'OK') {

        // get the lat and lng
        $lat = $resp['results'][0]['geometry']['location']['lat'];
        $lng = $resp['results'][0]['geometry']['location']['lng'];

        // verify if data is complete
        if ($lat && $lng) {

            return array(
                'lat' => $lat,
                'lng' => $lng,
            );
        } else {
            return false;
        }
    } else {
        return false;
    }
}

In order to find post based on this answer one must have the zip code stored into the post_meta table to fetch the lati and longi and the formula that is given in the code to find the max and min boundaries will get the lat and lng itself. I hope I gave the answer in detail if not please feel free to write comments.

Leave a Comment