5

Say someone searches for "John Smith". Using the search results template on the Craft website, my search results are then a list of titles for entries that include the term "John Smith". For example:

  • Dave Taylor wins award
  • New building built

The user experience is quite poor as there is no indication that these articles are in any way related to "John Smith". What I'm trying to do is output the following:

  • Dave Taylor wins award

...with the help of his brother John Smith,...

  • New building built

...architect John Smith was instrumental...

i.e. something similar to Google search. Any ideas how I could go about this?

6

I think creating your own Twig filter is your best bet. So, create a filter that takes a string, searches that for another string and returns an extract. It could do this by using some regular expression hocus pocus, I guess.

{{ entry.bodyText | extract('your search term', 3, 3) }}

would be how you'd use it (assuming, for example, that your filter accepts the three arguments searchTerm, wordsBefore and wordsAfter).

| improve this answer | |
  • 1
    To add to what Paul mentioned, there's some snippets in this SE thread that might be useful when crafting an excerpt/highlighting plugin. – RitterKnight Feb 27 '15 at 2:53
  • Thanks, both. I figured this would be the way to go but I just wanted to make sure I wasn't overlooking an easier solution. – Bruce Johnson Feb 27 '15 at 17:52
4

If I understand you correctly, you want to "highlight" your search query in the results. Your own Twig filter would be the cleanest way to do this, but you don't need to write one. Beware of putting too much logic in your templates, but this would also work nicely, using the native replace filter:

{# Get the search query and break it into individual terms #}
{% set query = craft.request.getParam( 'q' ) %}
{% set searchTerms = query | trim | split( ' ' ) %}

{# Build an associated array w/ terms and the replacement string #}
{% set replace = {} %}
{% for term in searchTerms %}
{% set replace = replace | merge( { (term) : '<strong>' ~ term ~ '</strong>' } ) %}
{% endfor %}

{# Loop through your search results, replacing the terms for all neccessary fields..#}
{% for entry in entries %}
    <li>
        <a href="{{ entry.url }}">{{ entry.title | replace( replace ) | raw }}</a>
        <p>{{ entry.bodyText | replace( replace ) | raw }}
    </li>
{% endfor %}

With that, all your search terms will be wrapped in tags – or whatever else you'd want to highlight them.

EDIT: Reading over, I realize I did misunderstand the question – you need to extract parts of the content matching the search query, not highlight the terms in titles, excerpts or whatever. The commenter above me is correct; you'd need a custom filter to accomplish your goal (without going insane). Apologies for the wrong answer; I'll leave it up, though.

| improve this answer | |
  • Thanks anyway. My question probably could have been clearer. – Bruce Johnson Feb 27 '15 at 17:53
  • Thanks for your answer. I just want to add that if a term is part of an URL for instance, the link will break. – Mario Apr 20 '17 at 12:16

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.