Ad for Tradeomics

Drupal Location Module Proximity Filter

A client requested this feature for a niche social network project. It seemed simple enough.  They wanted to filter a list of places closest to the registered member by proximity/distance from their zip code.

After the first attempt there seemed to be some issues with the module.  Luckily, a few contributors to the Location module were making some great progress on the module. Just in time.  I could not have done it without all the hard work the community was putting into the module. It still took me some to time figure it out.  If you are trying to do the same thing, hopefully this post will help.

Module Versions:

  • Drupal 6.17
  • Content Profile 6.x-1.0
  • Location 6.x-3.1
  • Views 6.x-2.11
  • CCK 6.x-2.7

First we need to check the settings for the Location module. The path is “admin/settings/locaton”. If you want to get the latitude & longitude automatically from your user’s street address we will need to set up the geocoding options. Select your country & the map you will be using.  I am using the Google Maps API.  Be sure to get your Google Map API Key & add it under “configure parameters” next to your country.

When a user saves their profile after filling out their location, the geocoding settings will create the latitude & longitude.

I am going to assume you already know how to use CCK & Views. Using the Content Profile module for as you guessed it, user profiles.

Set up your view list your nodes that you will be filtering.  In my case I added the Node Title for the fields.

The only thing we need to do is add the Location: Distance / Proximity filter, in this example I will be exposing a form so that the user can select the distance in miles to filter the content. See the below image for the details:

Now your view is ready!  Test out your exposed form.

A couple of things to check for if it doesn’t seem to be working:

  • Below the preview area of your view is the query.  You should see a latitude & longitude in the query.
  • If you are using Google Maps, you will need an API Key to geocode the addresses.
  • Check the database to see that your user & content is geocoding a latitude & longitude. If the location info was filled out prior to setting this up you will have to remove the location information, save, then fill out the fields again. It will not geocode the address otherwise. Took me awhile to figure that one out.

I hoped this helped you. If you have any questions leave a comment.

[update] I changed the zip code source from Node: Nid to the User’s locations in the filter options. When the User’s Location is selected as source it will get your location even when using the Content Profile module.  Without needing to pass the argument and using relationships.

If you have nodes that have already had location data added they will not be geocoded.  So what I did was export the database table “Locations” as a CSV.  Googled for a batch geocode app using CSV.  Be sure in the options that it geocodes from using the street, city, state, and zip.  In the app I found it appended a latitude & longitude column.  I renamed the columns to the lat & lng column names in MySQL.  Then just imported that back into my “Locations” table. Used the Mac app Sequel Pro to import and export.

[update 2] Still had some issues getting the filter to show up for all users. This fix seemed to do the trick. Changed the Filter: Distance/Proximity origin to “Use PHP code to determine latitude / longitude”.  Use the following PHP code:

1
2
3
4
5
6
7
global $user;
$latitude = db_result(db_query("SELECT location.latitude AS latitude, location.longitude AS longitude FROM location location LEFT JOIN location_instance location_instance ON location.lid = location_instance.lid LEFT JOIN node node ON location_instance.vid = node.vid WHERE node.uid='%d' AND type='profile'", $user->uid));
$longitude = db_result(db_query("SELECT location.longitude AS longitude FROM location location LEFT JOIN location_instance location_instance ON location.lid = location_instance.lid LEFT JOIN node node ON location_instance.vid = node.vid WHERE node.uid='%d' AND type='profile'", $user->uid));
return array(
'longitude' => $longitude,
'latitude' => $latitude
);

Comments are closed.