1

*** Edited the question

I have a code that used to work fine on Craft 2 and I don't understand what I need to change to make it work on Craft 3.

I am using form to filter through a channel of entries based on two fields - checkbox field with handle blogcategory and tags field with handle blogTags.

Here is the code of the form I am using for the filtering (worked perfectly on craft 2):

{% set blogcategory =  craft.request.getQuery('blogcategory') %}
{% set tags =  craft.request.getQuery('tags') %}

<form action="" method="get">
    <div class="filtering">

        <div class="section {% if blogcategory %}active{% endif %}" >
            <span class="title">category</span>
            <select name="blogcategory">
                <option value="">Any Category</option>
                {% for option in craft.fields.getFieldByHandle('blogcategory').settings.options %}
                    <option value="{{ option.value }}">{{ option.label }}</option>
                {% endfor %}
            </select>
        </div>
        <div class="section {% if tags %}active{% endif %}">        
            <span class="title">tags</span>
            <select name="tags">
                <option value="">Any tags</option>
                {% for tag in craft.tags.group('blogTags') %}
                    <option value="{{ tag.title }}">{{ tag.title }}</option>
                {% endfor %}
            </select>
        </div>  
    </div>
    <div class="submit">    
        <input type="submit" value="filter">
    </div>  
</form>

And here is the code for displaying the entries:

<div class="container"> 
    {% set entries = craft.entries.section('blog') %}
    {% set search_terms = '' %}
    
    {% if blogcategory %}
        {% set search_terms = search_terms ~ ' blogcategory:' ~ blogcategory %}
    {% endif %}

    {% if tags %}
        {% set search_terms = search_terms ~ ' tags:' ~ tags %}
    {% endif %}

            
    {% if search_terms %}
        {% set entries = entries.search(search_terms) %}
    {% endif %}
    
    {% for entry in entries %}
        <div class="thumb">
            <a href="{{ entry.url }}">{{ entry.title }}</a>
        </div>
    {% endfor %}
</div>

The problem is that after submitting the form with the desired filtering, none of the entries are showing up at all. It seems like the .serach function is not working...

I am a bit lost how to start understanding what fails under Craft 3...

4
  • What have you tried to debug this? Are you getting any errors when you view the page with this template? What do the errors say? Any deprecation messages in the Utilities? – MoritzLost May 27 at 7:28
  • Thanks for the help. There are no error messages but the filtering doesn't work. For some reason, after submitting the form, none of the entries are showing up. It seems like the .search function is not working... – Less and More Collective May 27 at 8:44
  • The first thing I'm noticing is that you're not executing the query. In Craft 3, you have to explicitly execute entry queries: {% for entry in entries.all() %}. Does this change anything? – MoritzLost May 27 at 8:54
  • Did all the tasks from Craft 2 to 3 run properly? As is, are your entries indexed properly? Does searching in your control panel work? If not, run ./craft resave/entries --update-search-index (docs). – Oli May 27 at 12:43
2

I'm not sure why your search is not working in this instance (though it might be because you're not executing the query, see my comment). But in general, fulltext search is way less precise, I would only do that if you need to support actual search terms. Since you're only filtering by categories and tags, I wouldn't search by category/tag titles, but instead use IDs to match the selected categories/tags directly. This will be way more precise, avoid edge-cases and will be much faster as well.

First you'll need to adjust your form so the select fields use IDs instead of titles as their value:

{# category filter #}
<option value="{{ option.id }}">{{ option.label }}</option>

{# tag filter #}
<option value="{{ tag.id }}">{{ tag.title }}</option>

Then adjust your query to query your blogcategory and tags field directly by ID:

{% set entries = craft.entries.section('blog') %}
{% set blogcategory =  craft.request.getQuery('blogcategory') %}
{% set tags =  craft.request.getQuery('tags') %}

{% if blogcategory %}
    {% do entries.blogcategory(blogcategory) %}
{% endif %}

{% if tags %}
    {% do entries.tags(tags) %}
{% endif %}     

Finally, make sure to actually execute the query:

{% for entry in entries.all() %}
    {# output results #}
{% endfor %}
2
  • Thanks! worked like charm beside one thing. {{ option.id }} was giving me an error so I stayed with the original code of {{ option.value }}. – Less and More Collective May 27 at 13:43
  • Ah I see, I missed that you're accessing the field settings instead of the available categories. I guess the field settings have their options set in the format expected by the templates. Might be a bit more intuitive to query available categories/tags instead, in this case accessing the ID will work normally. – MoritzLost May 27 at 13:50

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.