Search with string, entry type and category

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
2
down vote

favorite












So I have been asked to build a resource center just like hubspot's. (insert rolleyes here)



https://www.hubspot.com/resources



You can click into a type, and then click at topic and it creates a url like so:



https://www.hubspot.com/resources/ebook/advertising



You can also click a topic and then click type and it will do the same.



I have this part pretty much working. In my category template I have done this:



 Filter by type:

<a href="/resources/case-studies/category.slug">case studies</a>

<br/><br/>

<a href="/resources/ebooks/category.slug">ebooks</a>

<br/><br/>

<a href="/resources/webinars/category.slug}">webinars</a>

<br/><br/>

<a href="/resources/whitepapers/category.slug">whitepapers</a>


then I have a routes for each type setup like this:



if the URI looks like this:



/resources/case-studies/*



Loads this template:



resources/_filtered.html



and in that template filtered I do the filtering like this:



 % set resourceType = craft.request.segment(2) %

% set resourceCatSlug = craft.request.segment(3) %

% set resourceCat = craft.categories.slug(resourceCatSlug).first() %

resourceType

resourceCat

% set filteredEntries = craft.entries(
section: ['resources'],
orderBy: postDate: SORT_DESC,
type: resourceType,
relatedTo: resourceCat,
).all() %


This all works and I planned to do the same method on the resources types to get to the filtered template.



But where I'm stuck is it was also requested that you could filter your search even further with a string search.



So from this:



<form class="control txt-center" action=" url('resources/search/results-filtered') ">

<input class="input margin-auto-left-right display-block is-narrow-field " type="search" name="q" placeholder="Search">

<button class="margin-top-1 button is-info" role="button" type="submit"> Search the library </button>




How can I pass entry type and category to my filtered results?



% set searchTerm = craft.app.request.getParam('q') %
% set searchResults = craft.entries.search(searchTerm).section('resources').orderBy('score') %


PS, If anyone has a more elegant way to handle this I'm all ears!







share|improve this question
























    up vote
    2
    down vote

    favorite












    So I have been asked to build a resource center just like hubspot's. (insert rolleyes here)



    https://www.hubspot.com/resources



    You can click into a type, and then click at topic and it creates a url like so:



    https://www.hubspot.com/resources/ebook/advertising



    You can also click a topic and then click type and it will do the same.



    I have this part pretty much working. In my category template I have done this:



     Filter by type:

    <a href="/resources/case-studies/category.slug">case studies</a>

    <br/><br/>

    <a href="/resources/ebooks/category.slug">ebooks</a>

    <br/><br/>

    <a href="/resources/webinars/category.slug}">webinars</a>

    <br/><br/>

    <a href="/resources/whitepapers/category.slug">whitepapers</a>


    then I have a routes for each type setup like this:



    if the URI looks like this:



    /resources/case-studies/*



    Loads this template:



    resources/_filtered.html



    and in that template filtered I do the filtering like this:



     % set resourceType = craft.request.segment(2) %

    % set resourceCatSlug = craft.request.segment(3) %

    % set resourceCat = craft.categories.slug(resourceCatSlug).first() %

    resourceType

    resourceCat

    % set filteredEntries = craft.entries(
    section: ['resources'],
    orderBy: postDate: SORT_DESC,
    type: resourceType,
    relatedTo: resourceCat,
    ).all() %


    This all works and I planned to do the same method on the resources types to get to the filtered template.



    But where I'm stuck is it was also requested that you could filter your search even further with a string search.



    So from this:



    <form class="control txt-center" action=" url('resources/search/results-filtered') ">

    <input class="input margin-auto-left-right display-block is-narrow-field " type="search" name="q" placeholder="Search">

    <button class="margin-top-1 button is-info" role="button" type="submit"> Search the library </button>




    How can I pass entry type and category to my filtered results?



    % set searchTerm = craft.app.request.getParam('q') %
    % set searchResults = craft.entries.search(searchTerm).section('resources').orderBy('score') %


    PS, If anyone has a more elegant way to handle this I'm all ears!







    share|improve this question






















      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      So I have been asked to build a resource center just like hubspot's. (insert rolleyes here)



      https://www.hubspot.com/resources



      You can click into a type, and then click at topic and it creates a url like so:



      https://www.hubspot.com/resources/ebook/advertising



      You can also click a topic and then click type and it will do the same.



      I have this part pretty much working. In my category template I have done this:



       Filter by type:

      <a href="/resources/case-studies/category.slug">case studies</a>

      <br/><br/>

      <a href="/resources/ebooks/category.slug">ebooks</a>

      <br/><br/>

      <a href="/resources/webinars/category.slug}">webinars</a>

      <br/><br/>

      <a href="/resources/whitepapers/category.slug">whitepapers</a>


      then I have a routes for each type setup like this:



      if the URI looks like this:



      /resources/case-studies/*



      Loads this template:



      resources/_filtered.html



      and in that template filtered I do the filtering like this:



       % set resourceType = craft.request.segment(2) %

      % set resourceCatSlug = craft.request.segment(3) %

      % set resourceCat = craft.categories.slug(resourceCatSlug).first() %

      resourceType

      resourceCat

      % set filteredEntries = craft.entries(
      section: ['resources'],
      orderBy: postDate: SORT_DESC,
      type: resourceType,
      relatedTo: resourceCat,
      ).all() %


      This all works and I planned to do the same method on the resources types to get to the filtered template.



      But where I'm stuck is it was also requested that you could filter your search even further with a string search.



      So from this:



      <form class="control txt-center" action=" url('resources/search/results-filtered') ">

      <input class="input margin-auto-left-right display-block is-narrow-field " type="search" name="q" placeholder="Search">

      <button class="margin-top-1 button is-info" role="button" type="submit"> Search the library </button>




      How can I pass entry type and category to my filtered results?



      % set searchTerm = craft.app.request.getParam('q') %
      % set searchResults = craft.entries.search(searchTerm).section('resources').orderBy('score') %


      PS, If anyone has a more elegant way to handle this I'm all ears!







      share|improve this question












      So I have been asked to build a resource center just like hubspot's. (insert rolleyes here)



      https://www.hubspot.com/resources



      You can click into a type, and then click at topic and it creates a url like so:



      https://www.hubspot.com/resources/ebook/advertising



      You can also click a topic and then click type and it will do the same.



      I have this part pretty much working. In my category template I have done this:



       Filter by type:

      <a href="/resources/case-studies/category.slug">case studies</a>

      <br/><br/>

      <a href="/resources/ebooks/category.slug">ebooks</a>

      <br/><br/>

      <a href="/resources/webinars/category.slug}">webinars</a>

      <br/><br/>

      <a href="/resources/whitepapers/category.slug">whitepapers</a>


      then I have a routes for each type setup like this:



      if the URI looks like this:



      /resources/case-studies/*



      Loads this template:



      resources/_filtered.html



      and in that template filtered I do the filtering like this:



       % set resourceType = craft.request.segment(2) %

      % set resourceCatSlug = craft.request.segment(3) %

      % set resourceCat = craft.categories.slug(resourceCatSlug).first() %

      resourceType

      resourceCat

      % set filteredEntries = craft.entries(
      section: ['resources'],
      orderBy: postDate: SORT_DESC,
      type: resourceType,
      relatedTo: resourceCat,
      ).all() %


      This all works and I planned to do the same method on the resources types to get to the filtered template.



      But where I'm stuck is it was also requested that you could filter your search even further with a string search.



      So from this:



      <form class="control txt-center" action=" url('resources/search/results-filtered') ">

      <input class="input margin-auto-left-right display-block is-narrow-field " type="search" name="q" placeholder="Search">

      <button class="margin-top-1 button is-info" role="button" type="submit"> Search the library </button>




      How can I pass entry type and category to my filtered results?



      % set searchTerm = craft.app.request.getParam('q') %
      % set searchResults = craft.entries.search(searchTerm).section('resources').orderBy('score') %


      PS, If anyone has a more elegant way to handle this I'm all ears!









      share|improve this question











      share|improve this question




      share|improve this question










      asked Aug 17 at 14:14









      Danielle Frappier

      1447




      1447




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          2
          down vote



          accepted










          Without completely changing your direction and following in Hubspot's footsteps. From the search box set the query param for the page ?q=search-text then as the page refreshes grab the query % set query = craft.request.getParam('q') %. Then loop over your filteredEntries results only showing those entries who's title has the query.



          % for item in filteredEntries %
          % if query in item.title %
          …
          % endif %
          % endfor %


          Containment Operator



          You could also accomplish the filter by textual query in Javascript:
          Filter by search using text found in element within each div






          share|improve this answer






















          • Keep in mind this won't order them by score and it will only search the title. So chances are high your first results are no actual matches as one would expect but titles that randomly contain the characters. In fact I don't see any reason not to include the search param to the query.
            – Robin Schambach
            Aug 17 at 17:29











          • I would say Robin's answer would be your best bet since you are adding the search within the entries query.
            – aran
            Aug 17 at 17:40

















          up vote
          3
          down vote













          A more elegant way to handle it would be to use PHP, rely on a more complex routing system with default values, don't rely on segments but on routing parameters. Use real URLs instead of relative paths and build your URLs dynamically instead of just inserting the string hard coded in order to be able to filter by multiple values without loosing the already set filters.



          However - to include your parameters all you need to do



          % set searchResults = craft.entries
          .search(searchTerm)
          .section('resources')
          .type(resourceType)
          .orderBy('score')
          .relatedTo(resourceCat)
          %


          I would create a dynamic rule



          $event->rules = [
          'pattern' => '/resources/<type:S+>/<category:S+>/<search:[a-zA-Z0-9-]+>',
          'route' => 'module/search/search-elements',
          'defaults' => [
          'type' => '',
          'category' => '',
          'search' => '',
          ]
          ];


          and search in PHP



          public function actionSearchElements(string $type, string $category, string $search)


          You can then create a Twig function/filter in order to change those



          <a href="/resources/ebooks/category.slug">ebooks</a>


          to something like



          <a href=" getSearchUrl(category: category.slug) ">ebooks</a>


          And build your URL based on your route params + overwrite the new category. It will make it more re-usable and easier to change in the future if you would like to add an additional parameter or need to change the order you only need to change one place instead of many






          share|improve this answer




















          • Thank you so much for alway thoughtful answers. You have helped me out so much with this website build. I really appreciate all your help!
            – Danielle Frappier
            Aug 17 at 17:11










          Your Answer







          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "563"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcraftcms.stackexchange.com%2fquestions%2f27346%2fsearch-with-string-entry-type-and-category%23new-answer', 'question_page');

          );

          Post as a guest






























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          2
          down vote



          accepted










          Without completely changing your direction and following in Hubspot's footsteps. From the search box set the query param for the page ?q=search-text then as the page refreshes grab the query % set query = craft.request.getParam('q') %. Then loop over your filteredEntries results only showing those entries who's title has the query.



          % for item in filteredEntries %
          % if query in item.title %
          …
          % endif %
          % endfor %


          Containment Operator



          You could also accomplish the filter by textual query in Javascript:
          Filter by search using text found in element within each div






          share|improve this answer






















          • Keep in mind this won't order them by score and it will only search the title. So chances are high your first results are no actual matches as one would expect but titles that randomly contain the characters. In fact I don't see any reason not to include the search param to the query.
            – Robin Schambach
            Aug 17 at 17:29











          • I would say Robin's answer would be your best bet since you are adding the search within the entries query.
            – aran
            Aug 17 at 17:40














          up vote
          2
          down vote



          accepted










          Without completely changing your direction and following in Hubspot's footsteps. From the search box set the query param for the page ?q=search-text then as the page refreshes grab the query % set query = craft.request.getParam('q') %. Then loop over your filteredEntries results only showing those entries who's title has the query.



          % for item in filteredEntries %
          % if query in item.title %
          …
          % endif %
          % endfor %


          Containment Operator



          You could also accomplish the filter by textual query in Javascript:
          Filter by search using text found in element within each div






          share|improve this answer






















          • Keep in mind this won't order them by score and it will only search the title. So chances are high your first results are no actual matches as one would expect but titles that randomly contain the characters. In fact I don't see any reason not to include the search param to the query.
            – Robin Schambach
            Aug 17 at 17:29











          • I would say Robin's answer would be your best bet since you are adding the search within the entries query.
            – aran
            Aug 17 at 17:40












          up vote
          2
          down vote



          accepted







          up vote
          2
          down vote



          accepted






          Without completely changing your direction and following in Hubspot's footsteps. From the search box set the query param for the page ?q=search-text then as the page refreshes grab the query % set query = craft.request.getParam('q') %. Then loop over your filteredEntries results only showing those entries who's title has the query.



          % for item in filteredEntries %
          % if query in item.title %
          …
          % endif %
          % endfor %


          Containment Operator



          You could also accomplish the filter by textual query in Javascript:
          Filter by search using text found in element within each div






          share|improve this answer














          Without completely changing your direction and following in Hubspot's footsteps. From the search box set the query param for the page ?q=search-text then as the page refreshes grab the query % set query = craft.request.getParam('q') %. Then loop over your filteredEntries results only showing those entries who's title has the query.



          % for item in filteredEntries %
          % if query in item.title %
          …
          % endif %
          % endfor %


          Containment Operator



          You could also accomplish the filter by textual query in Javascript:
          Filter by search using text found in element within each div







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Aug 18 at 18:00









          Robin Schambach

          13.3k1427




          13.3k1427










          answered Aug 17 at 15:56









          aran

          2,1871122




          2,1871122











          • Keep in mind this won't order them by score and it will only search the title. So chances are high your first results are no actual matches as one would expect but titles that randomly contain the characters. In fact I don't see any reason not to include the search param to the query.
            – Robin Schambach
            Aug 17 at 17:29











          • I would say Robin's answer would be your best bet since you are adding the search within the entries query.
            – aran
            Aug 17 at 17:40
















          • Keep in mind this won't order them by score and it will only search the title. So chances are high your first results are no actual matches as one would expect but titles that randomly contain the characters. In fact I don't see any reason not to include the search param to the query.
            – Robin Schambach
            Aug 17 at 17:29











          • I would say Robin's answer would be your best bet since you are adding the search within the entries query.
            – aran
            Aug 17 at 17:40















          Keep in mind this won't order them by score and it will only search the title. So chances are high your first results are no actual matches as one would expect but titles that randomly contain the characters. In fact I don't see any reason not to include the search param to the query.
          – Robin Schambach
          Aug 17 at 17:29





          Keep in mind this won't order them by score and it will only search the title. So chances are high your first results are no actual matches as one would expect but titles that randomly contain the characters. In fact I don't see any reason not to include the search param to the query.
          – Robin Schambach
          Aug 17 at 17:29













          I would say Robin's answer would be your best bet since you are adding the search within the entries query.
          – aran
          Aug 17 at 17:40




          I would say Robin's answer would be your best bet since you are adding the search within the entries query.
          – aran
          Aug 17 at 17:40










          up vote
          3
          down vote













          A more elegant way to handle it would be to use PHP, rely on a more complex routing system with default values, don't rely on segments but on routing parameters. Use real URLs instead of relative paths and build your URLs dynamically instead of just inserting the string hard coded in order to be able to filter by multiple values without loosing the already set filters.



          However - to include your parameters all you need to do



          % set searchResults = craft.entries
          .search(searchTerm)
          .section('resources')
          .type(resourceType)
          .orderBy('score')
          .relatedTo(resourceCat)
          %


          I would create a dynamic rule



          $event->rules = [
          'pattern' => '/resources/<type:S+>/<category:S+>/<search:[a-zA-Z0-9-]+>',
          'route' => 'module/search/search-elements',
          'defaults' => [
          'type' => '',
          'category' => '',
          'search' => '',
          ]
          ];


          and search in PHP



          public function actionSearchElements(string $type, string $category, string $search)


          You can then create a Twig function/filter in order to change those



          <a href="/resources/ebooks/category.slug">ebooks</a>


          to something like



          <a href=" getSearchUrl(category: category.slug) ">ebooks</a>


          And build your URL based on your route params + overwrite the new category. It will make it more re-usable and easier to change in the future if you would like to add an additional parameter or need to change the order you only need to change one place instead of many






          share|improve this answer




















          • Thank you so much for alway thoughtful answers. You have helped me out so much with this website build. I really appreciate all your help!
            – Danielle Frappier
            Aug 17 at 17:11














          up vote
          3
          down vote













          A more elegant way to handle it would be to use PHP, rely on a more complex routing system with default values, don't rely on segments but on routing parameters. Use real URLs instead of relative paths and build your URLs dynamically instead of just inserting the string hard coded in order to be able to filter by multiple values without loosing the already set filters.



          However - to include your parameters all you need to do



          % set searchResults = craft.entries
          .search(searchTerm)
          .section('resources')
          .type(resourceType)
          .orderBy('score')
          .relatedTo(resourceCat)
          %


          I would create a dynamic rule



          $event->rules = [
          'pattern' => '/resources/<type:S+>/<category:S+>/<search:[a-zA-Z0-9-]+>',
          'route' => 'module/search/search-elements',
          'defaults' => [
          'type' => '',
          'category' => '',
          'search' => '',
          ]
          ];


          and search in PHP



          public function actionSearchElements(string $type, string $category, string $search)


          You can then create a Twig function/filter in order to change those



          <a href="/resources/ebooks/category.slug">ebooks</a>


          to something like



          <a href=" getSearchUrl(category: category.slug) ">ebooks</a>


          And build your URL based on your route params + overwrite the new category. It will make it more re-usable and easier to change in the future if you would like to add an additional parameter or need to change the order you only need to change one place instead of many






          share|improve this answer




















          • Thank you so much for alway thoughtful answers. You have helped me out so much with this website build. I really appreciate all your help!
            – Danielle Frappier
            Aug 17 at 17:11












          up vote
          3
          down vote










          up vote
          3
          down vote









          A more elegant way to handle it would be to use PHP, rely on a more complex routing system with default values, don't rely on segments but on routing parameters. Use real URLs instead of relative paths and build your URLs dynamically instead of just inserting the string hard coded in order to be able to filter by multiple values without loosing the already set filters.



          However - to include your parameters all you need to do



          % set searchResults = craft.entries
          .search(searchTerm)
          .section('resources')
          .type(resourceType)
          .orderBy('score')
          .relatedTo(resourceCat)
          %


          I would create a dynamic rule



          $event->rules = [
          'pattern' => '/resources/<type:S+>/<category:S+>/<search:[a-zA-Z0-9-]+>',
          'route' => 'module/search/search-elements',
          'defaults' => [
          'type' => '',
          'category' => '',
          'search' => '',
          ]
          ];


          and search in PHP



          public function actionSearchElements(string $type, string $category, string $search)


          You can then create a Twig function/filter in order to change those



          <a href="/resources/ebooks/category.slug">ebooks</a>


          to something like



          <a href=" getSearchUrl(category: category.slug) ">ebooks</a>


          And build your URL based on your route params + overwrite the new category. It will make it more re-usable and easier to change in the future if you would like to add an additional parameter or need to change the order you only need to change one place instead of many






          share|improve this answer












          A more elegant way to handle it would be to use PHP, rely on a more complex routing system with default values, don't rely on segments but on routing parameters. Use real URLs instead of relative paths and build your URLs dynamically instead of just inserting the string hard coded in order to be able to filter by multiple values without loosing the already set filters.



          However - to include your parameters all you need to do



          % set searchResults = craft.entries
          .search(searchTerm)
          .section('resources')
          .type(resourceType)
          .orderBy('score')
          .relatedTo(resourceCat)
          %


          I would create a dynamic rule



          $event->rules = [
          'pattern' => '/resources/<type:S+>/<category:S+>/<search:[a-zA-Z0-9-]+>',
          'route' => 'module/search/search-elements',
          'defaults' => [
          'type' => '',
          'category' => '',
          'search' => '',
          ]
          ];


          and search in PHP



          public function actionSearchElements(string $type, string $category, string $search)


          You can then create a Twig function/filter in order to change those



          <a href="/resources/ebooks/category.slug">ebooks</a>


          to something like



          <a href=" getSearchUrl(category: category.slug) ">ebooks</a>


          And build your URL based on your route params + overwrite the new category. It will make it more re-usable and easier to change in the future if you would like to add an additional parameter or need to change the order you only need to change one place instead of many







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Aug 17 at 15:59









          Robin Schambach

          13.3k1427




          13.3k1427











          • Thank you so much for alway thoughtful answers. You have helped me out so much with this website build. I really appreciate all your help!
            – Danielle Frappier
            Aug 17 at 17:11
















          • Thank you so much for alway thoughtful answers. You have helped me out so much with this website build. I really appreciate all your help!
            – Danielle Frappier
            Aug 17 at 17:11















          Thank you so much for alway thoughtful answers. You have helped me out so much with this website build. I really appreciate all your help!
          – Danielle Frappier
          Aug 17 at 17:11




          Thank you so much for alway thoughtful answers. You have helped me out so much with this website build. I really appreciate all your help!
          – Danielle Frappier
          Aug 17 at 17:11

















           

          draft saved


          draft discarded















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcraftcms.stackexchange.com%2fquestions%2f27346%2fsearch-with-string-entry-type-and-category%23new-answer', 'question_page');

          );

          Post as a guest













































































          Comments

          Popular posts from this blog

          What does second last employer means? [closed]

          List of Gilmore Girls characters

          Confectionery