I need to alter the search behavior of a WordPress site where the theme doesn't use searchform.php at all (it's the Divi theme). I'd rather not employ a plugin to do this as the site has many plugins already.
The default state of the page is to show "all posts from all categories" (/?cat=0) with a category list dropdown generated using wp_dropdown_categories() that allows the user to select other categories.
The desired use case is:
The user selects a category from a dropdown
The browser goes to the selected category's archive
The user types a search query into the search box on the category archive with the intent of seeing only posts and pages in that category that contain the search term.
I figured I could use the pre_get_posts hook to do this. So I did the following:
function search_by_cat()
{
global $wp_query;
if ( is_search() ) {
$currenturl = add_query_arg( $wp->query_vars, home_url( $wp->request ) );
$previousurl = wp_get_referer();
if ( strpos( $previousurl, '/category/' ) !==false ) {
$searchcategoryurl = untrailingslashit( $previousurl ) . $currenturl;
wp_redirect( $searchcategoryurl );
exit();
}
}
}
add_action('pre_get_posts', 'search_by_cat');
But this just results in ERR_TOO_MANY_REDIRECTS in the browser. I think it might be because the user is submitting a search that results in the same destination as the referrer. How do I break out of the redirect loop so I can (essentially) redisplay the page of results? Or is my entire approach all wrong? Is there a better way?
Here's the general idea from my comments, you'll need to change the CPT and taxonomy types to match your code. Tax queries are a little weird because of the nested array syntax. The comments should hopefully help understand it more.
add_action(
'pre_get_posts',
static function (WP_Query $query) {
// We only want to run on the main search query
if (!$query->is_search() || !$query->is_main_query()) {
return;
}
// Attempt to get the parameter, or default to 0
$category_id = (int)($_GET['category_id'] ?? 0);
if (!$category_id) {
return;
}
// Since we're search by a taxonomy, we probably want to bind it to a type, too
$query
->set(
'post_type',
// Change as needed
'events'
);
$query
->set(
'tax_query',
[
// See this for specifics: https://developer.wordpress.org/reference/classes/wp_query/#taxonomy-parameters
[
// Change as needed
'taxonomy' => 'event-type',
'field' => 'term_id',
'terms' => [$category_id],
],
]
);
}
);
Related
I am trying to include a users custom meta named 'sageaccountnumber' within the 'filter by registered customer' section of the WooCommerce orders list as shown below:
I already have the custom meta field named 'sageaccountnumber' working with the following PHP code:
add_action( 'personal_options_update', 'sab_save_sageaccount_user_profile_fields' );
add_action( 'edit_user_profile_update', 'sab_save_sageaccount_user_profile_fields' );
function sab_save_sageaccount_user_profile_fields( $user_id ) {
if ( !current_user_can( 'edit_user', $user_id ) ) {
return false;
}
update_user_meta( $user_id, 'sageaccountnumber', $_POST['sageaccountnumber'] );
}
When searching for a registered customer I would like to include the user meta 'sageaccountnumber' within the search and display matching results.
I understand this uses AJAX within the file class-wc-ajax.php. This is the function in question: https://wp-kama.com/plugin/woocommerce/function/WC_AJAX::json_search_customers
I do not know alot about AJAX and I have not been able to find a way to include a custom user meta value in this search. I have not found anyone else doing this.
Any guidance or suggestions would be much appreciated? Thank you.
After getting lost with trying to understand the class-wc-ajax.php file, I completely missed a more obvious and simple solution. Here is the code I am using which works perfectly. I hope this helps others looking for similar solution.
This filter-hook allows you to add an additional meta_query to the existing search parameters. This will also allow your custom user meta to display in AJAX searches from the Orders & Subscriptions pages.
If you have a custom meta field setup for your users, simply change 'sageaccountnumber' to the name of your meta and it will be included in the AJAX search results.
add_filter ('woocommerce_customer_search_customers', 'sab_sageaccount_order_subscription_search', 10, 4);
function sab_sageaccount_order_subscription_search ($filter, $term, $limit, $type){
if ($type == 'meta_query'){ $filter['meta_query'][] = array('key' => 'sageaccountnumber', 'value' => $term, 'compare' => 'LIKE');
}
return $filter;
}
If you need to include the custom meta field in the normal users search, you can use the following code, again changing 'sageaccountnumber' to your custom meta name.
add_action( 'pre_user_query', 'sab_sageaccount_user_search' );
function sab_sageaccount_user_search( $query ) {
global $wpdb;
global $pagenow;
if (is_admin() && 'users.php' == $pagenow) {
if( empty($_REQUEST['s']) ){return;}
$query->query_fields = 'DISTINCT '.$query->query_fields;
$query->query_from .= ' LEFT JOIN '.$wpdb->usermeta.' ON '.$wpdb->usermeta.'.user_id = '.$wpdb->users.'.ID';
$query->query_where = "WHERE 1=1 AND (user_login LIKE '%".$_REQUEST['s']."%' OR ID = '".$_REQUEST['s']."' OR (meta_value LIKE '%".$_REQUEST['s']."%' AND meta_key = 'sageaccountnumber'))";
}
return $query;
}
I bought a WordPress theme for affiliate marketing business. I have 1000+ stores on my website and hence hundred of coupons on homepage.I simply write a short-code to fetch all coupons and they started to appear on homepage .All coupons are based on different categories.
How can i exclude a number of coupons from homepage and that is possible only if we can exclude some categories from homepage based on their IDs.
I Google it many times but each time i found "pre_get_posts" function to do so. But in my case, it's not working at all. The code is below
function exclude_category_home( $query ) {
if ( $query->is_home ) {
$query->set( 'cat', '-5' );
}
return $query;
}
add_filter( 'pre_get_posts', 'exclude_category_home' );
Through this code i am trying to exclude desired categories. I also tried to modified above code in different ways but none of my solution/idea worked.
What i think is the reason behind why above code is no working is the function only works for default "Category" option under "Posts"on Dashboard. And my categories are coming from another option on Dashboard that's "Coupons" -> "Offer Categories".
See screenshot: Offer Categories
May be or may be not, i need to modify the above function in a way that it can select my expected categories. But as i have lack of knowledge in PHP so i don't know what and how to do?
I'm badly stuck here and hoping to get some help from experts.
Thanks in advance
Try this code.
if(is_home() || is_front_page()){
$args_active_coupons['tax_query'][] = array(
'taxonomy' => 'offer_categories',
'field' => 'id',
'terms' => array(214),
'operator' => 'NOT IN',
);
}
If you want to hard code all the excluded category, you have to put your category ID with (-) prefix. e.g
function exclude_category_home( $query ) {
if ( $query->is_home ) {
$query->set( 'cat', '-<CAT_ID>, -<CAT_ID>, -<CAT_ID>' );
}
return $query;
}
add_filter( 'pre_get_posts', 'exclude_category_home' );
Here: CAT_ID should be excluded category id.
In another way, you could use a plugin:
https://wordpress.org/plugins/ultimate-category-excluder/
I have multiple custom post types. I need display country and location results. but currently show all post types results in search.php page. I need hide results for these post types post ,page, experience, trip-theme.
I m using default theme WordPress Seventeen theme
I have no idea how can do this. please help me.
Thank you.
Try this code
add_action( 'pre_get_posts', 'search_in_custom_post_type' );
function search_in_custom_post_type( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) {
$query->set( 'post_type', array( 'country', 'location' ) );
}
return $query;
}
When you register post type set one extra parameter for search.
FOR custom post type.
'exclude_from_search' => true,
https://codex.wordpress.org/Function_Reference/register_post_type
I am using WooCommerce on my Wordpress site. My homepage only has one category so the search would only search in that category (client wants the homepage to only have one category). Whenever I try to search for something from a different category, it simply says that product is nonexistent.
How can I change the location where it should search so I can make another page with all the products?
To alter the search query for only the home page to display products from a specific category, use the pre_get_posts hook
function include_category( $query ) {
if ( $query->is_home() && $query->is_main_query() ) {
$query->set('tax_query', array(array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => array("**term name here**") ) // replace **term name here** with the slug of the term you wish to show on the home page
));
}
}
add_action( 'pre_get_posts', 'include_category' );
Depending whether you've set a static page or latest blog posts page as your home page you'll need to change $query->is_home() with $query->is_front_page()
I have a custom post type named 'Company' and a basic search on the top right of the screen. Unfortunately, when submitting a basic search the search results populate companies instead of actual pages such as Resources or Tech Advisory Group. http://labbureau.wpengine.com/
I have modified my custom query to search only for pages and ignore all company posts however, the basic search is still displaying companies instead of the actual TITLES of the pages. What can be done of this?
Below is my custom query:
$keyword = $_GET['s'];
$wp_query = new WP_Query(
array(
's' => $keyword,
'post_type' => 'page',
'tax_query' => array(
'taxonomy' => 'company',
'operator' => 'NOT IN'
),
'orderby' => 'title'
)
);
Start of loop:
<?php if ( $wp_query->have_posts() ) while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
Try add hidden input in the search form with the post type you want to make the search on:
<input type="hidden" name="post_type" value="post_type_name" />
On your theme functions.php use this code
function searchfilter($query) {
if ($query->is_search && !is_admin() ) {
$query->set('post_type',array('page'));
}
return $query;
}
add_filter('pre_get_posts','searchfilter');
Here is a simple solution. Go to your Media Gallery and do a search for a file. If the search title is the same as the image title and no results display you have a conflicting query that is running rampant. More than likely this can be found in the functions.php file and is represented as a filter that looks like the following:
function search_filter( $query ) {
if ( $query->is_search ) {
$query->set( 'post_type', array('company') );
}
return $query;
}
add_filter('pre_get_posts','search_filter');
The function.php file is the king of the hill and will take over all other custom post types you have on your website. If you have multiple searches they will both search for the company post type regardless of whether or not you create a new WordPress query in a template. You need to comment out add_filter. In this example, you need to create a conditional statement for two different search loops. One of your search templates (HTML) needs to have a hidden input that can be retrieved by one of your conditional points to reference a new template with a new query. Do not try the conditional statement with custom post types because you will have to change this in more than one place if it needs to be changed. Here is an example of what this conditional would look like:
if(isset($_GET['search_simple']) && $_GET['search_simple'] = 'search' && !isset($_GET['hdr-search']))
{
get_template_part('loop-search');
}
else if(isset($_GET['search_simple']) && $_GET['search_simple'] = 'search' && isset($_GET['hdr-search']))
{
get_template_part('loop-search2');
}
else
{
get_template_part('loop-search-blog');
}