What I’m trying to do is filter a bunch of wordpress posts by distance between 2 coordinates. There is coordinates, a range and a category inputted by the user that are passed in the URL like this:
/?cat=0&s=5041GW&range=250&lat=51.5654368&lon=5.071263999999928
Then there are posts(not all of them) that have a lat and long field which I created using the plugin Advanced Custom Fields. These are the arguments I pass to get_posts to get the posts that are filtered by category:
$args = array(
'posts_per_page' => 24,
'category' => $_GET["cat"],
'orderby' => 'post_date',
'order' => 'DESC',
'post_type' => 'adressen',
'post_status' => 'publish',
);
Now what I’m trying to do is modify this so that when a range and location are actually passed, the posts will be filtered to only return posts with a location within the range(in kilometers) of the location the user searched for. I can’t seem to be able to find a good solution for this as I’m having a hard time working with wordpress and the plugins it has. I would really appreciate a solution I can understand.
This could be fairly expensive computationally. The straightforward way to do it would be to get all the posts that otherwise fit the criteria, and then loop through them all, discarding posts outside the specified range.
Difficulties arise because there is not a linear mapping between meters and lat/long. It depends on where you are on the earth. See this question for details. The PHPcoord library exists to make this calculation for you, but due to the slightly approximate nature of my proposed answer, I shall be using approximate methods described on this website using the Haversine formula.
I shall be using the following formulae:
To calculate the distance in km between two lat/lng coords:
where Ï is latitude in radians, λ is longitude in radians, R is earthâs radius (mean radius = 6,371km)
To calculate the destination given a starting latlng, distance, and bearing:
where θ is the bearing (clockwise from north), δ is the angular distance d/R, and d is the distance travelled. See atan2.
We shall therefore define the following helper functions:
(Runnable in ideone)
Now, the general process shall be:
few that are about right. This should not be too computationally
expensive, but is an approximation which might leave some edge posts
out, and include some posts that do not fit.
posts to just those that fit the bill. This is a computationally
expensive process, hence the first stage. The few posts excluded in
the first step will still be excluded. The bounding box could
potentially be made larger to accommodate.
The query you want to use shall include meta information:
see here for a useful guide to some of these meta queries
Then the posts are filtered down in the loop:
The WordPress code is untested, so apologies if errors remain. The general concept is correct though.