Quick and easy class created to modify the WP_Query on specific calls and pull in all posts within a radius from a given latitude and longitude.
-
-
Save jahir07/900f49d516d0219e89eddc6936bd6db5 to your computer and use it in GitHub Desktop.
WordPress Geo Location Query
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$locations = new WP_Query_Geo([ | |
'post_status' => 'publish', | |
'post_type' => 'ash_locations', // cpt with locations stored | |
'posts_per_page' => -1, | |
'lat' => $lat, // pass in latitude | |
'lng' => $lng, // pass in longitude | |
'distance' => 10 // distance to find properties in | |
]); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if( ! class_exists( 'WP_Query_Geo' ) ) { | |
class WP_Query_Geo extends WP_Query | |
{ | |
private $lat = NULL; | |
private $lng = NULL; | |
private $dist = NULL; | |
function __construct($args = []) | |
{ | |
if( !empty( $args['lat'] ) ) | |
$this->lat = $args['lat']; | |
if( !empty( $args['lng'] ) ) | |
$this->lng = $args['lng']; | |
if( !empty( $args['distance'] ) ) | |
$this->dist = $args['distance']; | |
if( !empty( $args['lat'] ) ) { | |
add_filter( 'posts_fields', [$this, 'posts_fields'], 10, 2 ); | |
add_filter( 'posts_join', [$this, 'posts_join'], 10, 2 ); | |
add_filter( 'posts_where', [$this, 'posts_where'], 10, 2 ); | |
add_filter( 'posts_orderby', [$this, 'posts_orderby'], 10, 2 ); | |
} | |
unset( $args['lat'], $args['lng'], $args['distance'] ); | |
parent::query($args); | |
# remove the filters again at the end (Resets for normal wp queries) | |
$this->remove_filters(); | |
} | |
/** | |
* Selects the distance from a haversine formula | |
*/ | |
public function posts_fields($fields) | |
{ | |
global $wpdb; | |
$fields .= sprintf(", ( 3959 * acos( | |
cos( radians( %s ) ) * | |
cos( radians( lat.meta_value ) ) * | |
cos( radians( lng.meta_value ) - radians( %s ) ) + | |
sin( radians( %s ) ) * | |
sin( radians( lat.meta_value ) ) | |
) ) AS distance ", $this->lat, $this->lng, $this->lat); | |
$fields .= ", lat.meta_value AS latitude "; | |
$fields .= ", lng.meta_value AS longitude "; | |
return $fields; | |
} // END public function posts_join($join, $query) | |
/** | |
* Makes joins as necessary in order to select lat/long metadata | |
*/ | |
public function posts_join($join, $query) | |
{ | |
global $wpdb; | |
$join .= " INNER JOIN {$wpdb->postmeta} AS lat ON {$wpdb->posts}.ID = lat.post_id "; | |
$join .= " INNER JOIN {$wpdb->postmeta} AS lng ON {$wpdb->posts}.ID = lng.post_id "; | |
return $join; | |
} // END public function posts_join($join, $query) | |
/** | |
* Adds where clauses to compliment joins | |
*/ | |
public function posts_where($where) | |
{ | |
$where .= ' AND lat.meta_key="ash_locations_location_latitude" '; | |
$where .= ' AND lng.meta_key="ash_locations_location_longitude" '; | |
$where .= " HAVING distance < {$this->dist}"; | |
return $where; | |
} // END public function posts_where($where) | |
/** | |
* order posts by distance, then any other term | |
* @param string $orderby | |
* @return string | |
*/ | |
public function posts_orderby($orderby) | |
{ | |
$orderby = " distance ASC, " . $orderby; | |
return $orderby; | |
} // END public function posts_orderby($orderby) | |
/** | |
* remove the filters from the query (this ensures we can keep our other queries clean) | |
* @return null | |
*/ | |
public function remove_filters() | |
{ | |
remove_filter( 'posts_fields', [$this, 'posts_fields'], 10, 2 ); | |
remove_filter( 'posts_join', [$this, 'posts_join'], 10, 2 ); | |
remove_filter( 'posts_where', [$this, 'posts_where'], 10, 2 ); | |
remove_filter( 'posts_orderby', [$this, 'posts_orderby'], 10, 2 ); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment