Not sure of the best way to progress with this but i'm trying to create an advanced search on a Craft site.

What it needs is a select dropdown for Authors, Categories and a normal text input. The search options can be stacked and used singularly.

I'm trying a couple of things which I'll post here if they work but any assistance would be grand.

Here is the basics to being with.

<form class="search" action="{{ url('news/results') }}">
    <div class="col col-33">
        <div class="filter">
            <select name="c">
            {% set categories = craft.categories.find({ group: 'news' }) %}
                {% for category in categories %}
                <option>{{ category.title }}</option>
            {% endfor %}
    <div class="col col-33">
    <div class="col col-33">
         <button type="submit" class="btn search">
                Begin Search

And then on the "search results" page for example...

{% set query = craft.request.getParam('q', 'c') %}
    {% set entries = craft.entries.search(query).order('score').section('news').limit(10) %}

        {% if entries|length %}

            {% for entry in entries %}

            {% endfor %}

        {% else %}
            <p>Your search for “{{ query }}” didn’t return any results.</p>
        {% endif %}

I know i'm probably missing something extremely obvious here as i'm sure it's fairly simple to achieve.

  • Hey Dominic, an example of any code that you've already tried would be helpful. As it stands right now, this is a pretty broad question, so we can't tell which direction you're currently headed in. – Lindsey D Aug 13 '14 at 19:57
  • Edited original to house some "code" – Dominic Leonard Aug 15 '14 at 14:54

I'm not sure if you can get multiple POST parameters with one getParam request (maybe it works if you request them as an array?).

What definitely works is to get the parameters separately:

{% set c = craft.request.getParam('c') %}
{% set q = craft.request.getParam('q') %}

{% set query = c ~ ' ' ~ q %}



{# Request the category parameter
 --> see other answer on how to proceed with this #}
{% set catParam = craft.request.getParam('c') %}

{# Request search parameters #}
{% set searchParamQ = craft.request.getParam('q') %}
{% set searchParamR = craft.request.getParam('r') %}
{% set searchParamS = craft.request.getParam('s') %}
{% set searchParamT = craft.request.getParam('t') %}

{# Set `searchParam` before conditionals #}
{% set searchParam = '' %}

{# Add parameters with `OR` logic #}
{% set searchParam = searchParamQ ? searchParam ~ ' OR ' ~ searchParamQ : searchParam %}
{% set searchParam = searchParamR ? searchParam ~ ' OR ' ~ searchParamR : searchParam %}
{% set searchParam = searchParamS ? searchParam ~ ' OR ' ~ searchParamR : searchParam %}
{% set searchParam = searchParamT ? searchParam ~ ' OR ' ~ searchParamR : searchParam %}

{# Beautify `searchParam` #}
{% set searchParam = searchParam|trim|trim('OR ') %}
  • Thanks for this. It does work in the sense that if one field is selected it'll display search results. But if two or more are entered it doesn't display any. what would really be cool is it listed the parameters with and/or function between them. – Dominic Leonard Sep 4 '14 at 12:33
  • Hey @dominic, you should really look into that other approach I posted and NOT use the search() parameter for you categories! I was close to delete this answer because of that. – carlcs Sep 4 '14 at 13:05
  • What do you mean with "two or more entered"? Are there other parameters besides c and q you didn't mention in the question? Yes, you can conditionally add OR to the search string, but what types of parameters these are is important, because you should really avoid feeding all of them into search()! – carlcs Sep 4 '14 at 13:11

You should process your two POST parameters differently. One is responsible for your search parameter in your results template and the other should go into a relatedTo parameter. That's why I recommend to get them separately (it's probably not even possible to get them with a single getParam, but I'm not sure).

Here's how I'd proceed with the category parameter 'c'. For starters I'd use the category's slug as the value, just to be save.


{% for category in categories %}
    <option value="{{ category.slug }}">{{ category.title }}</option>
{% endfor %}

Then use that slug to grab the right category with a craft.categories ElementCriteriaModel. Use first() to get the first (and only) category model that matches the criteria and use it to compose the relation parameter. The category is the taget element because you select the category from your "News" entry and not the other way round.


{% set searchParam = craft.request.getParam('q') %}
{% set catSlug = craft.request.getParam('c') %}

{% set cat = craft.categories.group('news').slug(catSlug).first %}
{% set relationParam = catSlug ? {targetElement: cat} : '' %}

{% set entries = craft.entries.section('news').relatedTo(relationParam).search(searchParam) %}

{% if entries|length %}

    {% for entry in entries %}
        <p>{{ entry.title }}</p>
    {% endfor %}

{% else %}

    <p>Your search for “{{ searchParam }}” in “{{ cat.title }}” didn’t return any results.</p>

{% endif %}
  • this is great. what if I want to be able to search in multiple category-groups. how can I have more than one targetElement? – portnull Sep 14 '14 at 20:34
  • @portnull sorry totally forgot about your question. You do this similar to how you combine criteria in other parameters. There's an extra section in the Craft Docs Article "The relatedTo Param" about this: "Passing Multiple Relation Criteria", because the syntax is a little confusing. – carlcs Oct 29 '14 at 16:03
  • I'm way late to the party but I also found that along with this thread, this one was also very helpful. – Damon Sep 16 '15 at 18:23

Your Answer

