x
 
Create New Page
 View Previous Changes    ( Last updated by moonbeetle )

Custom search: using PHP with the Query module EE2

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 && 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!