PHPackages                             birgir/geo-query - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. birgir/geo-query

ActiveWordpress-plugin[Utility &amp; Helpers](/categories/utility)

birgir/geo-query
================

Modify the WP\_Query to support the geo\_query parameter. Uses the Haversine SQL optimization by Ollie Jones.

0.2.1(2y ago)683.0k13[5 issues](https://github.com/birgire/geo-query/issues)MITPHPPHP &gt;=5.3.3

Since Mar 10Pushed 1y ago5 watchersCompare

[ Source](https://github.com/birgire/geo-query)[ Packagist](https://packagist.org/packages/birgir/geo-query)[ Docs](https://github.com/birgire/geo-query)[ RSS](/packages/birgir-geo-query/feed)WikiDiscussions master Synced yesterday

READMEChangelogDependencies (1)Versions (11)Used By (0)

WordPress plugin: Geo Query
===========================

[](#wordpress-plugin-geo-query)

[![Build Status](https://camo.githubusercontent.com/0143d11fff140d79f17c9610379195a92358fb4c04190ec04b97d947160fcfc7/68747470733a2f2f7472617669732d63692e6f72672f626972676972652f67656f2d71756572792e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/birgire/geo-query)[![GitHub license](https://camo.githubusercontent.com/e682e4f12baab6dcf8ba9fd13fc65202791005907c731b85cbe72d9446ab68f9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f626972676972652f67656f2d71756572792e737667)](https://github.com/birgire/geo-query/blob/master/LICENCE)[![Packagist](https://camo.githubusercontent.com/d200e64cd5516ef4d3d2a6355edb7b890b22cc616cc4c6ba89468c1b6d2d3cc9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6269726769722f67656f2d71756572792e737667)](https://packagist.org/packages/birgir/geo-query)

### Description

[](#description)

This plugin adds a support for the `geo_query` part of the `WP_Query` and `WP_User_Query`.

Supports geo data stored in post/user meta or in a custom table.

It uses the Haversine SQL implementation by Ollie Jones (see [here](http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/)).

The plugin works on PHP 5.3+.

It supports the GitHub Updater.

Activate the plugin and you can use the `geo_query` parameter in all your `WP_Query` and `WP_User_Query` queries.

Few examples are here below, e.g. for the Rest API.

### Installation

[](#installation)

Upload the plugin to the plugin folder and activate it.

To install dependencies with Composer (not required):

```
composer install

```

or

```
php composer.phar install

```

within our folder. See here for more information on how to install Composer.

Then play with the example below, in your theme or in a plugin.

Have fun ;-)

### Example - Basic `WP_Query` usage:

[](#example---basic-wp_query-usage)

Here's an example of the default input parameters of the `geo_query` part:

```
$args = [
    'post_type'           => 'post',
    'posts_per_page'      => 10,
    'ignore_sticky_posts' => true,
    'orderby'             => [ 'title' => 'DESC' ],
    'geo_query'           => [
        'lat'                =>  64,                                // Latitude point
        'lng'                =>  -22,                               // Longitude point
        'lat_meta_key'       =>  'geo_lat',                         // Meta-key for the latitude data
        'lng_meta_key'       =>  'geo_lng',                         // Meta-key for the longitude data
        'radius'             =>  150,                               // Find locations within a given radius (km)
        'order'              =>  'DESC',                            // Order by distance
        'distance_unit'      =>  111.045,                           // Default distance unit (km per degree). Use 69.0 for statute miles per degree.
        'context'            => '\\Birgir\\Geo\\GeoQueryHaversine', // Default implementation, you can use your own here instead.
    ],
];
$query = new WP_Query( $args );

```

### Example - Rest API usage:

[](#example---rest-api-usage)

Here's a modified example from @florianweich:

```
add_filter( 'rest_query_vars', function ( $valid_vars ) {
	return array_merge( $valid_vars, [ 'geo_location' ] );
} );

add_filter( 'rest_post_query', function( $args, $request ) {
	$geo = json_decode( $request->get_param( 'geo_location' ) );
	if ( isset( $geo->lat, $geo->lng ) ) {
		$args['geo_query'] = [
			'lat'                =>  (float) $geo->lat,
			'lng'                =>  (float) $geo->lng,
			'lat_meta_key'       =>  'geo_lat',
			'lng_meta_key'       =>  'geo_lng',
			'radius'             =>  ($geo->radius) ? (float) $geo->radius : 50,
		];
	}
	return $args;
}, 10, 2 );

```

Test it with e.g.:

```
https://example.com/wp-json/wp/v2/posts?geo_location={"lat":"64.128288","lng":"-21.827774","radius":"50"}

```

One can use `rest_{custom-post-type-slug}_query` filter for a custom post type.

### Example - Basic `WP_User_Query` usage:

[](#example---basic-wp_user_query-usage)

Here's an example from @acobster:

```
$args = [
  'role'      => 'subscriber',
  'geo_query' => [
    'lat'          => 47.236,
    'lng'          => -122.435,
    'lat_meta_key' => 'geo_lat',
    'lng_meta_key' => 'geo_lng',
    'radius'       => 1,
    'context'      => '\\Birgir\\Geo\\GeoQueryUserHaversine',
  ],
];

$query = new WP_User_Query( $args );

```

### Example - Basic `WP_Query` usage for fetching lat/lng data from a custom table with Haversine formula:

[](#example---basic-wp_query-usage-for-fetching-latlng-data-from-a-custom-table-with-haversine-formula)

```
$args = array(
   	'post_type'           => 'post',
   	'posts_per_page'      => 10,
   	'ignore_sticky_posts' => true,
   	'orderby'             => array( 'title' => 'DESC' ),
	'geo_query' => array(
		'table'         => 'custom_table', // Table name for the geo custom table.
		'pid_col'       => 'pid',          // Column name for the post ID data
		'lat_col'       => 'lat',          // Column name for the latitude data
		'lng_col'       => 'lng',          // Column name for the longitude data
		'lat'           => 64.0,           // Latitude point
		'lng'           => -22.0,          // Longitude point
		'radius'        => 1,              // Find locations within a given radius (km)
		'order'         => 'DESC',         // Order by distance
		'distance_unit' => 111.045,        // Default distance unit (km per degree). Use 69.0 for statute miles per degree.
		'context'       => '\\Birgir\\Geo\\GeoQueryPostCustomTableHaversine', // Custom table implementation, you can use your own here instead.
	),
);

$query = new WP_Query( $args );

```

Check the unit test method `test_custom_table_in_wp_query()` as a more detailed example.

### Notes on the parameters:

[](#notes-on-the-parameters)

- The plugin assumes we store the latitudes and longitudes as custom fields ( post meta), so we need to tell the query about meta keys with the `'lat_meta_key'` and `'lng_meta_key'` parameters.
- Skipping the `'radius'` parameter means that no distance filtering will take place.
- If we use the `'order'` parameter within the `'geo_query'`, then it will be prepended to the native `'orderby'` parameter.
- The `'distance_unit'` parameter should be `69.0` for distance in statute miles, else `111.045` for distance in kilometers.
- If we want to use the optimized Haversine version by Ollie Jones, we use:

    ```
      'context' => '\\Birgir\\Geo\\GeoQueryHaversineOptimized'

    ```

    Notice that on our current plugin setup (i.e. fetching data from the LONGTEXT post meta fields) this isn't more performant than the default `GeoQueryHaversine` class.

    A future work could be to use a custom table with indexes, for the optimization to work.
- If we create our own implementation of the Haversine formula, for example the `GeoQueryCustom` class, we just have to make sure it implements the `GeoQueryInterface` interface:

    ```
      'context' => 'GeoQueryCustom'

    ```

### Feedback

[](#feedback)

Any suggestions are welcomed.

### Changelog

[](#changelog)

0.2.3 (2024-10-29)

- Fix: Deprecated creation of dynamic property. Props @lukasbesch

0.2.2 (2024-01-05)

- Bump composer/installers to ^2.0.0. Props @wujekbogdan

0.2.1 (2023-07-26)

- Fix deprecated notice in PHP 8.1 #24

0.2.0 (2020-04-25)

- Support for fetching points from a custom table and doing Haversine formula in WP\_Query.

0.1.1 (2019-01-23)

- Fixed #14. Fixed the user query ordering. Props @baden03

0.1.0 (2018-08-06)

- Added support for user queries. Props @acobster
- Fixed Travis issue. Travis runs successfully for PHP 7.2, 7.1,7,5.6 when installed via Composer and also 5.4 when installed without Composer. Skip the 5.4 Composer check for now.

0.0.7 (2018-06-27)

- Fixed #10. Use ^1.0.0 for composer installer. Props @wujekbogdan

0.0.6 (2017-11-16)

- Fixed #6. Support floating point radius. Props @wujekbogdan
- Added integration tests.

0.0.5 (2017-02-26)

- Added fallback for those that don't use Composer
- Removed the vendor directory

0.0.4 (2017-02-26)

- Fixed #4. Props @billzhong .

0.0.3 (2015-04-29)

- Fixed #2. Fixed a typo. Props @Ben764 and @con322.

0.0.2 (2015-03-10)

- Added: Support for the GitHub Updater.
- Updated: README.md
- Changed: Use distance\_value instead of distance\_in\_km in SQL, since we can use miles by changing the distance\_unit parameter.

0.0.1 - Init

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance27

Infrequent updates — may be unmaintained

Popularity33

Limited adoption so far

Community18

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 96.4% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~340 days

Recently: every ~464 days

Total

10

Last Release

1070d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/5312384?v=4)[Birgir Erlendsson](/maintainers/birgire)[@birgire](https://github.com/birgire)

---

Top Contributors

[![birgire](https://avatars.githubusercontent.com/u/5312384?v=4)](https://github.com/birgire "birgire (81 commits)")[![billzhong](https://avatars.githubusercontent.com/u/1644011?v=4)](https://github.com/billzhong "billzhong (1 commits)")[![lukasbesch](https://avatars.githubusercontent.com/u/241689?v=4)](https://github.com/lukasbesch "lukasbesch (1 commits)")[![wujekbogdan](https://avatars.githubusercontent.com/u/533954?v=4)](https://github.com/wujekbogdan "wujekbogdan (1 commits)")

---

Tags

distancegeo-queryhaversine-formulawordpresswordpress-pluginwp-querywordpress

### Embed Badge

![Health badge](/badges/birgir-geo-query/health.svg)

```
[![Health](https://phpackages.com/badges/birgir-geo-query/health.svg)](https://phpackages.com/packages/birgir-geo-query)
```

###  Alternatives

[roots/bedrock

WordPress boilerplate with Composer, easier configuration, and an improved folder structure

6.5k456.5k2](/packages/roots-bedrock)[helsingborg-stad/municipio

A bootstrap theme for creating municipality sites.

4028.3k10](/packages/helsingborg-stad-municipio)[roots/wp-stage-switcher

WordPress plugin that allows you to switch between different environments from the admin bar

374458.3k3](/packages/roots-wp-stage-switcher)[vinkla/wordplate

The WordPlate boilerplate

2.2k5.3k](/packages/vinkla-wordplate)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
