While the simple search can be sufficient and the channel:entries tag can be very powerful given the many tag parameters, sometimes you just want to do a search on more than just an entry title or a custom field value. Sometimes you want both or maybe even more criteria to match against. The Query module (Add-ons > Modules > Query module) allows you to create custom queries with the benefit that you can specify what data you want fetched, only the data you want.
The tricky part is how to pass the submitted form data to the query module AND allow pagination.
Example: a form that allows searching entry titles for a keyword and matching a certain custom field against a selection
PART ONE
This part goes at the top of your template. PHP must be allowed and the parsing order for PHP has to be set on INPUT
<?php
session_start();
if($_POST)
{
// Sanitize POST data!
// Strip out all non alphanumeric characters except space, hyphen and underscore
$keyword = preg_replace('/[^a-zA-Z0-9_-\s]/','',$_POST['keyword']);
// Match submitted selection against allowed values or reset to a default
$productstatus = (in_array($_POST['productstatus'], array('forrent','forsale','used')))?$_POST['productstatus']:'forrent';
// Put everything in a session as we want to preserve this data for pagination
$_SESSION['keyword'] = $keyword;
$_SESSION['productstatus'] = $productstatus;
}
?>
{preload_replace:keyword="<?php echo $_SESSION['keyword'];?>"}
{preload_replace:productstatus="<?php echo $_SESSION['productstatus'];?>"}
PART TWO
This part is where we output the used search keyword and the search results.
Note that we use the Query module as we need to do a lookup in two tables
1. matching the search keyword against an entry title (table: exp_channel_titles)
2. matching a selection against a custom field value (table: exp_channel_data)
Note: The custom field that we test against has an ID of 14 in this example, hence
field_id_14. Change this according for your project to the ID of YOUR custom field.
<p>Search keyword: <em>{keyword}</em></p>
{!-- Search query --}
{exp:query
limit="10"
paginate="top"
sql="SELECT ct.title, ct.url_title
FROM exp_channel_titles ct
INNER JOIN exp_channel_data cd
ON ct.entry_id = cd.entry_id
WHERE (ct.title LIKE '%{keyword}%' AND cd.field_id_14 LIKE '%{productstatus}%' AND ct.status = 'Open')
ORDER BY ct.title ASC"
}
{if count == 1}<ul>{/if}
<li><a href="{site_url}products/detail/{url_title}">{title}</a></li>
{if count > 0 && count == total_results}</ul>{/if}
{paginate}
<p>Page {current_page} of {total_pages} pages {pagination_links}</p>
{/paginate}
{/exp:query}
PART THREE
This part can reside on the same template or wherever you want.
It’s a very basic search form with a text input field and a dropdown menu
<form name="seachform" method="post" action="{path='search'}">
<input type="search" name="keyword" maxlength="50" size="35" placeholder="Search keyword..." />
<select name="productstatus" id="productstatus">
<option value="forrent">For rent</option>
<option value="forsale">For sale</option>
<option value="used">Used</option>
</select>
<input type="submit" name="submit" value="Search" />
</form>
That’s it. Hope it helps. Got a better solution? Share it!
