Your use of pre_get_posts
is completely wrong.
pre_get_posts
is an action, not a filter. Check the source
do_action_ref_array( 'pre_get_posts', array( &$this ) );
Yes, add_filter
works because add_action
calls add_filter
, that is why your code will work. But as for proper usage, it is just plain wrong. If something is an action, use add_action()
. It just makes sense
WP_Query::is_search
(and WP_Query::is_search()
for that matter) returns true on any query where s
is passed to WP_Query
. Remember, the conditional tags inside WP_Query
are not set according to the URL, but according to the query vars passed to it. For the main query, the query vars passed to WP_Query
will come from parsing the URL.
pre_get_posts
alters all instances of WP_Query
, query_posts
and get_posts
, front end and back end regardless, so you would want to target only the main query if you only would want to target the main query. Additionally, you would only want to target the front end, specially for archives and search queries.
Here is an example on how to use pre_get_posts
correctly for the main query: (You can change the closure to normal spaghetti if you wish, just a note, only use closures if you're sure you would not want to remove the action later as anonymous functions can't be removed)
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin() // Only target front end,
&& $q->is_main_query() // Only target the main query
&& $q->is_search() // Only target the search page
) {
$q->set( 'post_type', ['my_custom_post_type', 'post'] );
}
});
To answer your question about the search widget, here is what I have found
The search widget simply call get_search_form()
There is no useful filter to specifically target the search widget. The filters available in get_search_form()
will target all forms which uses get_search_form()
With the above, you would need to create your own search widget with your own custom form
You can try the following: (Modified from the core search widget, note, everything is untested)
class My_Custom_Search extends WP_Widget {
/**
* Sets up a new Search widget instance.
*
* @since 1.0.0
* @access public
*/
public function __construct() {
$widget_ops = [
'classname' => 'widget_custom_search',
'description' => __( "A custom search form for your site.")
];
parent::__construct( 'custom-search', _x( 'Custom search', 'My custom search widget' ), $widget_ops );
}
/**
* Outputs the content for the current Search widget instance.
*
* @since 1.0.0
* @access public
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Search widget instance.
*/
public function widget( $args, $instance ) {
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
}
$form = '<form role="search" method="get" class="search-form" action="' . esc_url( home_url( '/' ) ) . '">
<label>
<span class="screen-reader-text">' . _x( 'Search for:', 'label' ) . '</span>
<input type="search" class="search-field" placeholder="' . esc_attr_x( 'Search …', 'placeholder' ) . '" value="' . get_search_query() . '" name="s" title="' . esc_attr_x( 'Search for:', 'label' ) . '" />
</label>
<input type="hidden" value="post" name="post_type" id="post_type" />
<input type="submit" class="search-submit" value="'. esc_attr_x( 'Search', 'submit button' ) .'" />
</form>';
echo $form;
echo $args['after_widget'];
}
/**
* Outputs the settings form for the Search widget.
*
* @since 1.0.0
* @access public
*
* @param array $instance Current settings.
*/
public function form( $instance ) {
$instance = wp_parse_args( (array) $instance, ['title' => '')];
$title = $instance['title'];
?>
<p><label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?> <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo esc_attr($title); ?>" /></label></p>
<?php
}
/**
* Handles updating settings for the current Search widget instance.
*
* @since 1.0.0
* @access public
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
* @return array Updated settings.
*/
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$new_instance = wp_parse_args((array) $new_instance, ['title' => '')];
$instance['title'] = sanitize_text_field( $new_instance['title'] );
return $instance;
}
}