How to Customize your Search Form to Selectively Modify Engine Weights
SearchWP’s engine configuration can be modified at runtime, allowing you to modify your search engine configuration based on customizations from user input. This walkthrough guides you through the process of adding form elements to your search form allowing visitors to customize their search experience.
For example: using SearchWP you can allow your site visitors to selectively search only titles. You could also allow them to optionally include searching Content. An engine could also be configured in real time to only search Documents within the Media library.
This article will cover customizing your search form to limit searches to Titles only, but this implementation can be customized in any way the SearchWP engine settings can be customized.
NOTE: As a starting point for this implementation you will need to configure your search engine with proper defaults. For example in order to build the document search portion you will need to ensure that Media is enabled for the engine, as SearchWP will not index disabled post types.
Step 1: Adding form elements
If you’re working with a supplemental search engine you can simply add the applicable form elements by hand when implementing your search form.
If instead you are working with native WordPress search forms (this includes native search Widgets) you will need to filter that form HTML to include your additional form controls. Native WordPress search forms are inserted in one of two methods:
- A file named
searchform.php
in your active theme directory - The
get_search_form()
function
NOTE: If you do not have a searchform.php
in your active theme directory, then your form is being built using get_search_form()
. For the purposes of this article you will need to create a searchform.php
in your active theme directory.
There isn’t an elegant way to insert additional form elements programmatically so if your theme does not have a file named searchform.php
in its directory, please create one. We will be customizing that file to include additional form elements in the search form.
[see_also url=”https://searchwp.com/docs/kb/customizing-theme-using-child-theme/” title=”Use a Child Theme here!” note=”Make sure you’re working within a Child Theme from this point forward.”]
Our searchform.php
should be based on WordPress’ native implementation. As defined in the Codex there are two potential structures for the search form: HTML4 and HTML5 (shown below, respectively)
<form role="search" method="get" id="searchform" | |
class="searchform" action="<?php echo esc_url( home_url( '/' ) ); ?>"> | |
<div> | |
<label class="screen-reader-text" for="s"><?php _x( 'Search for:', 'label' ); ?></label> | |
<input type="text" value="<?php echo get_search_query(); ?>" name="s" id="s" /> | |
<input type="submit" id="searchsubmit" | |
value="<?php echo esc_attr_x( 'Search', 'submit button' ); ?>" /> | |
</div> | |
</form> |
<form role="search" method="get" class="search-form" action="<?php echo home_url( '/' ); ?>"> | |
<label> | |
<span class="screen-reader-text"><?php echo _x( 'Search for:', 'label' ) ?></span> | |
<input type="search" class="search-field" | |
placeholder="<?php echo esc_attr_x( 'Search …', 'placeholder' ) ?>" | |
value="<?php echo get_search_query() ?>" name="s" | |
title="<?php echo esc_attr_x( 'Search for:', 'label' ) ?>" /> | |
</label> | |
<input type="submit" class="search-submit" | |
value="<?php echo esc_attr_x( 'Search', 'submit button' ) ?>" /> | |
</form> |
If you are not sure whether your theme has enabled support for the HTML5 search form, you will need to rename the searchform.php
from your Child Theme (so as to restore the default search form) and view your site in your browser, comparing the markup of your search form to the two examples.
Begin by populating your searchform.php
with the default form markup (either the HTML4 or HTML5 version). For the purposes of this article we will be using the HTML5 version. Here’s what it looks like in Twenty Fifteen as a Widget:
First we will add a checkbox to allow the visitor to restrict their search to Titles only. Our searchform.php now looks like this (note lines 4-7):
<form role="search" method="get" class="search-form" action="<?php echo home_url( '/' ); ?>"> | |
<label> | |
<span class="screen-reader-text"><?php echo _x( 'Search for:', 'label' ) ?></span> | |
<p> | |
<input type="checkbox" name="searchwp_limit_to_title" id="searchwp_limit_to_title" value="1" <?php if ( ! empty( $_REQUEST['searchwp_limit_to_title'] ) ) : ?>checked="checked"<?php endif; ?> /> | |
<label for="searchwp_limit_to_title"><?php esc_html_e( 'Limit to Titles', 'searchwp_child_theme' ); ?></label> | |
</p> | |
<input type="search" class="search-field" | |
placeholder="<?php echo esc_attr_x( 'Search …', 'placeholder' ) ?>" | |
value="<?php echo get_search_query() ?>" name="s" | |
title="<?php echo esc_attr_x( 'Search for:', 'label' ) ?>" /> | |
</label> | |
<input type="submit" class="search-submit" | |
value="<?php echo esc_attr_x( 'Search', 'submit button' ) ?>" /> | |
</form> |
The form renders like so:
While the checkbox has been added to the form, ticking it won’t change the search results at all. We need to tie this into SearchWP itself.
Step 2: Integrating with SearchWP
If writing code makes you nervous, there is an alternate step 2 which you may prefer.
SearchWP allows for customization of any engine configuration at runtime using the searchwp_engine_settings hook. We’re going to use that hook to check for our Limit to Titles checkbox being ticked. If it is, we’ll proceed by setting all content type weights to zero except Titles, thereby forcing a search by Title only.
<?php | |
function my_searchwp_engine_customizations( $settings, $query ) { | |
// print_r( $settings ); // uncomment this line to see the settings structure | |
// print_r( $query ); // uncomment this line to see the query structure | |
// Check for Title-only search | |
if ( empty( $_REQUEST['searchwp_limit_to_title'] ) ) { | |
return $settings; | |
} | |
// Set all weights to zero except Title | |
foreach ( $settings as $post_type => $post_type_settings ) { | |
// If the post type isn't enabled, skip to the next | |
if ( empty( $post_type_settings['enabled'] ) ) { | |
continue; | |
} | |
// Set all weights to zero excerpt Titles | |
foreach ( $post_type_settings['weights'] as $content_type => $weight ) { | |
switch ( $content_type ) { | |
case 'title': | |
continue; | |
break; | |
case 'tax': | |
// Taxonomies have a different structure | |
foreach ( $weight as $taxonomy => $taxonomy_weight ) { | |
$settings[ $post_type ]['weights'][ $content_type ][ $taxonomy ] = 0; | |
} | |
break; | |
case 'cf': | |
// Custom Fields have a different structure | |
foreach ( $weight as $custom_field_uid => $custom_field_weight_pair ) { | |
$settings[ $post_type ]['weights'][ $content_type ][ $custom_field_uid ]['weight'] = 0; | |
} | |
break; | |
default: | |
$settings[ $post_type ]['weights'][ $content_type ] = 0; | |
} | |
} | |
} | |
return $settings; | |
} | |
add_filter( 'searchwp_engine_settings_default', 'my_searchwp_engine_customizations', 10, 2 ); |
Walking through this snippet we can see on line 51 that we’re working with the default
engine. If you’re using a supplemental engine you will need to customize the searchwp_engine_settings_default
replacing default with your engine name e.g. searchwp_engine_settings_my_supplemental_engine
The my_searchwp_engine_customizations
callback receives two parameters, $settings
and $query
. The $settings
parameter is the engine configuration itself, and the $query
parameter is the submitted search. You can uncomment lines 4 and 5 and run a test search to see the full structure of each output in your browser.
Lines 7-10 check to make sure that the checkbox to Limit to Titles has been ticked. If it has, the rest of the function iterates through the $settings
array, resetting all defined weights to zero excerpt for the title. Finally, the $settings
array must be returned back to SearchWP for use during this search.
NOTE: This hook does not permanently modify your engine settings, the customization lasts only for this single request. This hook will be applied to any additional searches sent to this search engine during this request, so if you have multiple searches using the same engine on the same page load, they will all use this hook. If this is not desirable you will need to use this self-removing version of the above (see line 49).
Step 2 alternate: swap engines entirely
Instead of iterating through each stored weight in the engine configuration, you could also simply create a Supplemental Engine for each potential outcome and swap out the engine settings entirely.
As an example, you would have your Default search engine have your fully enabled engine configuration. You would then create a Supplemental Engine called Titles Only, which was configured exactly as you would want a Titles Only search to run (e.g. remove everything except Title for each post type):
You would use the same hook as Step 2, but instead of looping through the weights manually, you can just swap out the entire engine settings with your Titles Only engine settings, achieving the same result:
NOTE: The engine label is different than the engine name, the engine name is the monospaced version next to the label of a saved supplemental engine.
<?php | |
function my_searchwp_engine_customizations( $settings, $query ) { | |
// print_r( $settings ); // uncomment this line to see the settings structure | |
// print_r( $query ); // uncomment this line to see the query structure | |
// Check for Title-only search | |
if ( empty( $_REQUEST['searchwp_limit_to_title'] ) ) { | |
return $settings; | |
} | |
// Return the Titles Only engine settings | |
return SWP()->settings['engines']['titles_only']; // titles_only is the Supplemental Engine NAME (not label) | |
} | |
add_filter( 'searchwp_engine_settings_default', 'my_searchwp_engine_customizations', 10, 2 ); |
This achieves the same result as Step 2 but with less code and a UI-based way of configuring the alternate engine.