I’m trying to build a query to get the geographically closest entries, based on an Smart Map field value within a related entry.

Diagram of relationships and template

The following template tags were my first guess, but returned an empty result set.

{% set nearest = allUnitsCriteria.relatedPropertyField.smartMapField(params).order('distance') %}

What’s the best way to do this?

  • Are you referring to the Smart Map plugin? If so, your code looks correct as per the example in the docs (assuming field handles are correct). Have you tested whether allUnitsCriteria actually returns entries without the smartAddressField argument? What happens if you dump allUnitsCriteria|length? Also, what does the params object you pass to smartAddressField contain? Nov 14 '15 at 23:47
  • Thanks, @mmikkel. This is indeed a Smart Map field. The allUnitsCriteria is just a simplification. At present, it’s set to craft.entries.section('units').limit(null). params are set to { target: '_lat_,_lng_', range: 1000 }. The complication here is that the Unit entry doesn’t contain an address field, but instead links to a Property entry, which does contain an address field. Nov 15 '15 at 10:28

Being that the smartMapField attribute belongs to entries in the Property section, and not the entries in the Unit section, your current element criteria is a bit off (it basically assumes that the smartMapField property is found on the Unit entry models).

Basically, you'll need two element criterias to accomplish what you want.

The first criteria will pull Property entries based on their smartMapField value and the params object. The second one will pull Unit properties, by relation to the Property entries in the first criteria.

Finally, we'll need to use the group filter to output the unit entries in the correct order (i.e. those related to the nearest property entry first).

Important: It isn't 100% clear from your question, but I'm assuming that the relation between Units and Properties originates from a relatedPropertyField in the Units entries, rather than the other way around.

I haven't been able to test this, but I believe something like this should do the trick:

{% set nearest = craft.entries.section('units').relatedTo({
    targetElement : craft.entries.section('properties').smartMapField(params).order('distance').limit(null),
    field : 'relatedPropertyField'
}).limit(null).order('targets1.sortOrder')|group('relatedPropertyField.first().id') %}

Note the group filter applied to the nearest variable. This is needed to group the returned entries by their common Property relation. The group filter turns nearest into an array of grouped elements, which means that when you output the entries, you'll need a nested for loop:

{% for units in nearest %}
    {% for unit in units %}
    {% endfor %}
{% endfor %}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.