I'm trying to to display entries related to "all" the given categories instead of "any" using the updated relatedTo method provided in Craft 2.5.

In a related question, @BrandonKelly explains how to do this in the "Updated" portion of his answer. However, I still seem to be getting "any" behavior instead of entries matching "all" categories.

Here is an example URL if only one category in the Social Services group is selected


Here is an example URL if additional technology categories are also added:


So, ideally, I want to first filter the entries by the social service category, determined by segment 2 in the URL.

Then, I want to filter even further if there are types of technology in the URL.

Here is my code:

{% set slug = craft.request.getSegment(2) %}
{% set socialServiceCategory = craft.categories.group('socialServices').slug(slug).first() %}
{% set socialServiceCategoryId = socialServiceCategory.id %}

{% set technologyCategoryIds = [] %}
{% if craft.request.getParam('type') %}
{% set technologyCategoryIds = technologyCategoryIds|merge(craft.request.getParam('type')) %}
{% endif %}

{% set categoryIds = [socialServiceCategoryId]|merge(technologyCategoryIds) %}

{% set entries = craft.entries({
    section: 'solutions',
    relatedTo: { 
        targetElement: ['and']|merge(categoryIds)
}).order('listingType desc', 'title asc') %}

When the page loads with only the segment slug, and no query string, I get entries filtered by that category. However, once I add one or more technology IDs to the categoryIds array, I get all entries matching "any" categories in the categoryIds array.

Given a URL such as the 2nd example I displayed above, here is a dump of my categoryIds output:

array(3) { [0]=> string(2) "15" [1]=> string(2) "88" [2]=> string(3) "117" }

...which contains exactly the right categories I'd like to inclusively relate my entries to.

For the time being, I was able to get this working the way I need with pre-Craft 2.5 beta syntax for relatedTo using the following code:

{% set entries = entries.relatedTo(socialServiceCategoryId).order('listingType desc', 'title asc') %}

{% if technologyCategoryIds|length %}
{% set entries = entries.relatedTo(
    { targetElement: socialServiceCategoryId },
    { targetElement: technologyCategoryIds|join(',') }
).order('listingType desc', 'title asc') %}
{% endif %}

Some of the unexpected behavior here ended up being due to a bug in the new 2.5 relatedTo syntax. It was fixed in Craft 2.5.2724 Beta.


I can't test right now but just looking at this, could it be because your array has indexes whereas Brandon's demo is only the list of ids..?

  • That's just the output of the dump() method for twig. It's just showing the values at normal array indexes of 0, 1, and 2.
    – jthomas
    Nov 12 '15 at 20:13

Just done some testing here and I think it's a bug (I might be wrong).

I don't know how to explain this very well and I'm not sure if it's posted in the right place but here goes...

In the ElementRelationParamParser Class, parseRelationParam function (line 69), this test

if ($relatedTo[0] == 'and' || $relatedTo[0] == 'or')
    $glue = array_shift($relatedTo);

    $glue = 'or';

The 'and' or 'or' is actually here in your case


So basically, craft is always defaulting to 'or' at the moment from what I can see when using the new syntax (Old syntax works for me too btw).

  • Thanks for digging in to this, Oliver. I'll ping the craft guys as I'm sure they'll want to get this fixed in the beta.
    – jthomas
    Nov 14 '15 at 16:15
  • Hey No worries, pleasure :)
    – Oli
    Nov 15 '15 at 17:24

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