How to Customize your Search Form to Selectively Modify Engine Weights

Last updated December 18, 2018 « Knowledge Base

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:

  1. A file named searchform.php in your active theme directory
  2. 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.

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:

Screenshot of a native WordPress Search Widget output

A native WordPress Search Widget after adding searchform.php to a Child Theme

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>
view raw searchform.php hosted with ❤ by GitHub

The form renders like so:

WordPress native Search Widget with a customized checkbox to limit search to Titles in SearchWP

Added checkbox to force Title search

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 );
view raw functions.php hosted with ❤ by GitHub

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):

Search only Titles in a supplemental engine

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 );
view raw functions.php hosted with ❤ by GitHub

This achieves the same result as Step 2 but with less code and a UI-based way of configuring the alternate engine.

Fix Search on Your Site. No Coding Required!

Now you can utilize all of the content that's gone unrecognized by native WordPress search instantly with SearchWP

Get SearchWP