我想出了一个解决方案,在搜索表单上使用一个隐藏字段,稍后我们将在过滤器中检查该字段,以修改WP的默认搜索/重定向行为。
这是我使用的搜索表单。注意添加了隐藏字段barcode-reader
值为1
. 为了测试和演示,我将搜索表单添加到页面模板中。
<form role="search" method="get" class="search-form" action="<?php echo esc_attr( home_url( \'/\' ) ); ?>">
<label>
<span class="screen-reader-text"><?php echo _x( \'Search for:\', \'screen reader search label\', \'textdomain\' ); ?></span>
<div class="input-group">
<input type="search" class="search-field input-group-field" placeholder="<?php echo esc_attr_x( \'Search...\', \'search placeholder\', \'textdomain\' ); ?>" value="<?php echo get_search_query(); ?>" name="s" title="<?php echo esc_attr_x( \'Search for:\', \'textdomain\' ); ?>" />
<input type="hidden" value="1" name="barcode-reader" />
<div class="input-group-button">
<button type="submit" class="search-submit button" value="<?php echo esc_attr_x( \'Search\', \'search button\', \'textdomain\' ); ?>">Search</button>
</div>
</div>
</label>
</form>
(
从原始帖子中不清楚,但根据我所做的研究,条形码阅读器应该可以通过$_GET
可以使用它来代替我用于测试的隐藏字段。)这里,我们将检查条形码扫描仪是否正在使用帮助器功能执行此搜索wpse_is_barcode_search()
. 使用helper函数,这样我们就不必在这个实现中使用的多个挂钩之间复制逻辑。
如果我们使用扫描仪进行搜索,我们会将posts_search
筛选并对WP_Query
执行查询之前的实例。
/**
* Wire up our posts_search filter and change the $query.
*
* @param WP_Query $query The WP_Query instance (passed by reference).
*/
add_action( \'pre_get_posts\', \'wpse_barcode_search_pre_get_posts\' );
function wpse_barcode_search_pre_get_posts( $query ) {
// Bail if this search is not performed by the barcode scanner.
if ( ! wpse_is_barcode_search( $query ) ) {
return;
}
// Wire up the filter to modify the search SQL.
add_filter( \'posts_search\', \'wpse_barcode_posts_search\', 10, 2 );
// Set posts_per_page to one since we\'re only looking for an exact match anyway.
$query->set( \'posts_per_page\', 1 );
// (suggestion) Limit search to a particular post type.
// $query->set( \'post_type\', array( \'product\', ) );
}
下面是实际修改搜索SQL的过滤器。因为我们只想让它启动一次,所以过滤器会立即关闭。
/**
* Modify search query so that the search term looks for an exact
* match with the post title.
*
* @param string $search Search SQL for WHERE clause.
* @param WP_Query $wp_query The current WP_Query object.
*/
function wpse_barcode_posts_search( $search, $wp_query ) {
// We only want the search filter to fire once, so unhook it.
remove_filter( \'posts_search\', \'wpse_barcode_posts_search\', 10, 2 );
// Change the search SQL so that it checks if the search is equal to the post title.
$search = " AND (wp_posts.post_title = \'" . esc_sql( $wp_query->query_vars[\'s\'] ) . "\')";
return $search;
}
这段代码将用户重定向到我们找到的帖子的永久链接,而不是搜索结果页面。
/**
* Redirect to the permalink of the searched item if it was found using
* the barcode search.
*
* @link https://wordpress.stackexchange.com/a/128578/2807
*/
add_action( \'template_redirect\', \'wpse_barcode_search_success_redirect\' );
function wpse_barcode_search_success_redirect() {
global $wp_query;
if ( ! wpse_is_barcode_search( $wp_query ) ) {
return;
}
// If we have a post, redirect to it.
if ( \'1\' === $wp_query->found_posts ) {
wp_redirect( get_permalink( $wp_query->posts[\'0\']->ID ) );
exit;
}
}
最后,这里是帮助函数,用于确定我们是否正在使用条形码扫描仪执行搜索。应对此进行修改,以便与所使用的扫描仪配合使用(尤其是使用
$_REQUEST[\'barcode-reader\']
).
/**
* Helper function used to determine if a search is performed using
* the barcode scanner.
*
* @uses array $_REQUEST
* @param object $query
* @return bool
*/
function wpse_is_barcode_search( $query ) {
// Bail if $query is not an instance of WP_Query.
if ( ! ( $query instanceof WP_Query ) ) {
return false;
}
// Bail if this is the admin area.
if ( $query->is_admin() ) {
return false;
}
// Bail if this is not the search page or main query.
if ( ! $query->is_search() || ! $query->is_main_query() ) {
return false;
}
// Bail if this is not our special barcode search.
if ( ! isset( $_REQUEST[\'barcode-reader\'] ) || \'1\' !== $_REQUEST[\'barcode-reader\'] ) {
return false;
}
return true;
}