WordPress Custom search form with ACF custom fields and custom post type with taxonomies

If you ever been in a need of a Custom WordPress Search field, where you can search for example: for your custom post types, by custom taxonomies like category, or region, or maybe between dates, you are reading the right post! We will create a custom WP solution for this.
To avoid any inconvenience please note: Im pretty sure there are much better / cleaner approaches but it is working.
In rest of the post will try to general, but my case is specific to Events, where I had Custom taxonomies like : Regions, Categories, and added Advanced Custom Fields date fields every Event to determine Start & End date of the actual Event.
What we going to need:
- Custom Post type with taxonomies
- Advanced Search Form template to include anywhere on WP site
- Advanced Custom Fields plugin to create Date fields to our Events
- Assuming you know how to use any DatePicker
- Some custom function into functions.php which modifying the search query based on the passed string in URL
My Custom post type looks lie
Events (Custom Post type)
|Taxonomies|
|———-|—- Regions
|———-|—- Categories
Here is a superb guide how to create Custom Post Types & Taxonomies
Once thats done we should create a custom file that we can include anywhere in our template. I’m usually creating modules into a /inc directory (think it’s a good practice). For example create custom-search-form.php into /inc directory and include it into any of your templates like below:
<?php get_template_part('inc/custom-search-form'); ?>
Lets edit our custom-search-form.php module and place a Search form in it.
<div id="search">
<h2><?php _e('Search for an Event'); ?></h2>
<form method="get" class="searchandfilter" id="advanced-searchform" role="search" action="<?php echo esc_url( home_url( '/' ) ); ?>">
<!-- This is telling the form submit it is going to be search -->
<input type="hidden" name="s" value="">
<!-- This is limiting our Search for Events custom post type -->
<input type="hidden" name="post_type" value="events" />
<!-- This is adding an extra 'advanced' string to the URL so we can make difference between normal and this custom search -->
<input type="hidden" name="search" value="advanced">
<ul>
<!-- Event regions Select field -->
<li>
<?php // Loop through Event Regions taxonomy and create a dropdown / select field from the values $taxonomy = 'event_regions'; //change to your taxonomy $args = array( 'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => false
);
$tax_terms = get_terms($taxonomy, $args);
?>
<label for="event_regions">Regions</label>
<select name="event_regions" id="event_regions" class="postform">
<option value="" selected="selected">All Regions</option>
<?php if($tax_terms): ?>
<?php foreach ($tax_terms as $tax_term): ?>
<option value="<?php echo $tax_term->slug; ?>"><?php echo $tax_term->name; ?></option>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</select>
</li>
<!-- // Event regions Select field -->
<!-- Event Categories Select field -->
<li>
<?php // Loop through Event Categories taxonomy and create a dropdown / select field from the values $taxonomy = 'event_category'; //change to your taxonomy $args = array( 'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => false
);
$tax_terms = get_terms($taxonomy, $args);
?>
<label for="event_category">Categories</label>
<select name="event_category" id="event_category" class="postform">
<option value="" selected="selected">All Categories</option>
<?php if($tax_terms): ?>
<?php foreach ($tax_terms as $tax_term): ?>
<?php $title = $tax_term->name;
?>
<option value="<?php echo $tax_term->slug; ?>"><?php echo $title; ?></option>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</select>
</li>
<!-- // Event Categories Select field -->
<!-- Our Search Submit button -->
<li>
<input type="submit" value="Search Events">
</li>
<!-- // Our Search Submit button -->
<!-- Advanced Custom Field date fields -->
<li>
<label for="fromdate">Date from</label>
<input type="text" name="fromdate" id="date_timepicker_start" data-beatpicker="true" data-beatpicker-position="['right','*']" data-beatpicker-format="['DD','MM','YYYY'],separator:'/'"/>
<!-- Use any datepicker on these fields. I prefer Beatpicker. Date format does not matter too much now, set it to preferred in your country -->
</li>
<li>
<label for="todate">Date to</label>
<input type="text" name="todate" id="date_timepicker_end" data-beatpicker="true" data-beatpicker-position="['right','*']" data-beatpicker-format="['DD','MM','YYYY'],separator:'/'">
<!-- Use any datepicker on these fields. I prefer Beatpicker. Date format does not matter too much now, set it to preferred in your country -->
</li>
<!-- // Advanced Custom Field date fields -->
<!-- Below is completely optional my URL to the Events Archive page -->
<li>
<?php $events_page = get_field('events_page', 'options'); $events_page_id = $events_page->ID;
?>
<a href="<?php echo get_permalink($events_page_id); ?>">See all Events</a>
</li>
</ul>
</form>
</div>
If you made everything fine. Include the module into one of your page tempaltes to see if its showing up or not. This will not work yet, but after a form submission you should see something like that in the URL :
http://yourdomain.com/?s=&post_type=events&event_regions=london&event_category=somecategory&search=advanced&fromdate=2015%2F09%2F17&todate=2015%2F09%2F30
Lets see the magic! And create a function in functions.php to break down this URL and modify our search query for the search page.
function advanced_search_query( $query ) {
// set up execution conditions to only run when its submitted from our Advanced Search form
if ( isset( $_REQUEST['search'] ) && $_REQUEST['search'] == 'advanced' && !is_admin() && $query->is_search && $query->is_main_query() ) {
// limit queery for custom post type
$query->set( 'post_type', 'events' );
// Get query strings from URL and store the min a variable
$_region = $_GET['event_regions'] != '' ? $_GET['event_regions'] : '';
$_category = $_GET['event_category'] != '' ? $_GET['event_category'] : '';
$_fromdate = $_GET['fromdate'] != '' ? $_GET['fromdate'] : '';
$_todate = $_GET['todate'] != '' ? $_GET['todate'] : '';
// if Region is not empty limit the taxonomy to the specified
if( $_region != '' ) {
$taxquery = array(
array(
'taxonomy' => 'event_regions',
'field' => 'slug',
'terms' => $_region,
'operator'=> 'IN'
)
);
$query->set( 'tax_query', $taxquery );
}
// if Category is not empty limit the taxonomy to the specified
if( $_category != '' ) {
$taxquery = array(
array(
'taxonomy' => 'event_category',
'field' => 'slug',
'terms' => $_category,
'operator'=> 'IN'
)
);
$query->set( 'tax_query', $taxquery );
}
// if from Date & to Date is not empty limit the query BETWEEN the two dates
if ( $_fromdate != '' && $_todate !='') {
// here we should convert our date format (whtever date format we used) into WP regular date format 'Ymd'
$fromdate = date( 'Ymd', strtotime($_fromdate) );
$todate = date( 'Ymd', strtotime($_todate) );
$metaquery = array(
array(
'key' => 'event_start_date',
'value' => array($fromdate, $todate),
'compare' => 'BETWEEN',
'type' => 'DATE'
)
);
$query->set( 'meta_query', $metaquery );
}
return; // always return
}
}
add_action( 'pre_get_posts', 'advanced_search_query' );
Here we go. Hope that helps a few of you folks out there! If any problems, questions, fixes DO NOT hesitate to use the comments below.