I need to show products on a category page using the custom field.
For example, I have custom filed 'members_access_role' (multi check) and try
add_action( 'woocommerce_product_query', 'action_product_query', 10, 2 );
function action_product_query( $q, $query ) {
$meta_query = $q->get( 'meta_query');
$q->set( 'meta_query', array( array(
'key' => 'members_access_role',
'value' => 'wholesale',
'compare' => 'IN',
) ) );
$q->set( 'meta_query', $meta_query );
}
This doesnt work, i try change compare to 'LIKE', '=' but nothing too.
Please replace function like this:
add_action( 'woocommerce_product_query', 'action_product_query', 10, 2 );
function action_product_query( $q, $query ) {
$meta_query = $q->get( 'meta_query');
$meta_query[] = array(
'key' => 'members_access_role',
'value' => 'wholesale',
'compare' => 'IN'
);
$q->set( 'meta_query', $meta_query );
}
You seems to be setting meta_query twice and the 2nd time you are setting it is exactly the same as you received using get method.
Here is one way to write it
function action_product_query( $q, $query ) {
$meta_query = $q->get( 'meta_query'); //Get the query
//Update the array.
$meta_query[] = array(
'key' => 'members_access_role',
'value' => 'wholesale',
'compare' => '=',
);
//Set the updated value below.
$q->set( 'meta_query', $meta_query );
}
Related
I would like to hide products that are out of stock on archive pages.
But products containing tag "backorder" should be skipped.
I tried many options but the problem is that I can't combine meta_query and tax_query to do this.
Does anyone have suggestion on how to do this?
This is my current status:
add_filter( 'woocommerce_product_query_meta_query', 'shop_only_instock_products', 10, 2 );
function shop_only_instock_products( $meta_query, $query ) {
if( is_admin() || is_search() || ! is_shop()) return $meta_query;
$meta_query[] = array(
'key' => '_stock_status',
'value' => 'outofstock',
'compare' => '!='
);
print_r($meta_query);
}
add_filter( 'woocommerce_product_query_tax_query', 'filter_products_with_specific_product_tags', 9, 2 );
function filter_products_with_specific_product_tags( $tax_query, $query ) {
if( is_admin() || is_search() || ! is_shop()) return $tax_query;
$tax_query[] = array(
'taxonomy' => 'product_tag',
'field' => 'name',
'terms' => array('backorder'),
);
return $tax_query;
};
You can try woocommerce_product_query hook. I've not tested this code yet.
add_action( 'woocommerce_product_query', 'action_product_query', 10, 2 );
function action_product_query( $q, $query ) {
// Ignore this condition and test the behind codes firstly
// if( is_admin() || is_search() || ! is_shop()) return;
// Get any existing Tax query
$tax_query = $q->get( 'tax_query');
// Get any existing meta query
$meta_query = $q->get( 'meta_query');
// Define an additional tax query
$tax_query = array(
'taxonomy' => 'product_tag',
'field' => 'name', // backorder looks like slug
'terms' => array('backorder'),
'compare' => 'IN',
);
// Define an additional meta query
$meta_query = array(
'key' => '_stock_status',
'value' => 'outofstock',
'compare' => '!=',
);
// Set the new merged tax query
$q->set( 'tax_query', $tax_query );
// Set the new merged meta query
$q->set( 'meta_query', $meta_query );
}
You should use on backorder setting in your product inverntory. Set Out of stock visibility to true in your Woocommerce > Settings > Product > Inventory . You dont need any additional code for this.
I'm trying to figure out a direct link to display all sale items in the shop. URLs can usually filter out specific attributes and queries, so I was hopeful that this would be possible. So far, no luck.
My result turns up: no products found. But there are indeed products on sale.
I've tried the following:
add_filter( 'woocommerce_product_query_meta_query', 'filter_on_sale_products', 20, 1 );
function filter_on_sale_products( $meta_query ){
if( isset($_GET['onsale']) && $_GET['onsale'] ){
$meta_query[] = array(
'key' => '_sale_price',
'value' => 0,
'compare' => '>'
);
}
return $meta_query;
}
This should return all sale items by URL: https://www.example.com/shop/?onsale=1
Any advice would be appreciated
Your code contains some very minor errors.
You can use the woocommerce_product_query action hook instead. This should suffice:
function action_woocommerce_product_query( $q ) {
if ( is_admin() ) return;
// Isset & NOT empty
if ( isset( $_GET['onsale'] ) ) {
// Equal to 1
if ( $_GET['onsale'] == 1 ) {
// Function that returns an array containing the IDs of the products that are on sale.
$product_ids_on_sale = wc_get_product_ids_on_sale();
$q->set( 'post__in', $product_ids_on_sale );
}
}
}
add_action( 'woocommerce_product_query', 'action_woocommerce_product_query', 10, 1 );
check this link out
$args = array(
'post_type' => 'product',
'posts_per_page' => 8,
'meta_query' => array(
'relation' => 'OR',
array( // Simple products type
'key' => '_sale_price',
'value' => 0,
'compare' => '>',
'type' => 'numeric'
),
array( // Variable products type
'key' => '_min_variation_sale_price',
'value' => 0,
'compare' => '>',
'type' => 'numeric'
)
)
);
$loop = new WP_Query( $args );
I am using wordpress & I want elementor posts widget to show only posts which belong to a category & which belong to a specific institute.
Problem: Category part can be done inside widget itself but filtering institute (custom field) is my problem.
Solution I am trying:
add_action( 'elementor/query/institute-query', function( $query ) {
$meta_query = $query->get( 'meta_query' );
// Append our meta query instead of overwriting all elementors own metaqueries
if($meta_query == ""){
$meta_query = array();
}
// Append our meta query
$meta_query[] = [
'key' => 'course_institution',
'value' => [ 'University of Pennsylvania', 'university of pennsylvania', 'University-of-Pennsylvania', 'university-of-pennsylvania' ],
'compare' => 'or',
];
$query->set( 'meta_query', $meta_query );} );
You should use 'compare' => 'IN', insted of 'compare' => 'or',
add_action( 'elementor/query/institute-query', function( $query ) {
$meta_query = $query->get( 'meta_query' );
// Append our meta query instead of overwriting all elementors own metaqueries
if( !is_array( $meta_query ){
$meta_query = array();
}
// Append our meta query
$meta_query[] = [
'key' => 'course_institution',
'value' => [ 'University of Pennsylvania', 'university of pennsylvania', 'University-of-Pennsylvania', 'university-of-pennsylvania' ],
'compare' => 'IN',
];
$query->set( 'meta_query', $meta_query );
} );
I am working on a project where I need to list all hidden products in a page. I have created a shortcode for that and I have used following meta query, but it's not working.
$meta_query = array(
'key' => '_visibility',
'value' => array('hidden'),
'compare' => 'IN'
);
Any idea why this is not working? Thank you in advance for your help.
$args = array(
'post_type' => 'product',
'meta_key' => '_visibility',
'meta_value' => 'hidden'
);
$query = new WP_Query($args);
Then your usual loop worked for me :)
WooCommerce 3+ visibility has been changed to a taxonomy instead of post meta and if you're using WC()->query->get_tax_query() function call for building the args, you can just remove that call from setting tax_query.
IF you don't have access to the args or how they are built and it is ran through get_tax_query you can use the filter to remove the NOT IN tax query for visibility:
add_filter( 'woocommerce_product_query_tax_query', 'smyles_show_all_products' );
// do something that calls some fn that makes product query
remove_filter( 'woocommerce_product_query_tax_query', 'smyles_show_all_products' );
function smyles_show_all_products( $tax_query ) {
foreach( (array) $tax_query as $t_index => $t_query ){
if( isset( $t_query['taxonomy'], $t_query['operator'] ) && $t_query['taxonomy'] === 'product_visibility' && $t_query['operator'] === 'NOT IN' ){
unset( $tax_query[ $t_index ] );
break;
}
}
return $tax_query;
}
Use this
'meta_query' => array(
array(
'key' => '_visibility',
'value' => array( 'catalog', 'visible' ),
'compare' => 'IN'
)
)
I need to create a products archive page (usually the Shop page in WooCommerce) but displays ONLY the ON SALE products. Basically it should use the same template layout as that in the archive-product.php. There will be a link in the main menu that will direct to this page. How do I go about this?
UPDATE
I managed to filter out the ON SALE products with the code below placed just above the if ( have_posts() ) : line...
$args = array(
'post_type' => 'product',
'order' => 'ASC',
'paged' => $paged,
'meta_query' => array(
array(
'key' => '_sale_price',
'value' => 0,
'compare' => '>',
'type' => 'numeric'
)
)
);
query_posts( $args );
The code is placed in a copy of archive-product.php which I named archive-product_sale.php and made as a page template.
However, this only works for Simple products type and I need it to work for both Simple products and Variable products type.
#mirus' answer regarding the shortcode gave me the idea to check out how WooCommerce is querying only the on-sale items. Apparently WooCommerce has a wc_get_product_ids_on_sale() function that will return the IDs of the on-sale items. Then we can easily adjust the query using the post__in parameter to only return those specific items.
WooCommerce has a woocommerce_product_query hook in the class-wc-query.php class that allows for us to modify the query before it is run.... it is run on pre_get_posts which is the usual place for modifying the query. Using Woo's hook just means you let them handle the majority of the conditional logic about when this query modification should be applied.
add_action( 'woocommerce_product_query', 'so_20990199_product_query' );
function so_20990199_product_query( $q ){
$product_ids_on_sale = wc_get_product_ids_on_sale();
$q->set( 'post__in', $product_ids_on_sale );
}
I managed to filter out the ON SALE products with the code below placed just above the if ( have_posts() ) : line...
$args = array(
'post_type' => 'product',
'meta_query' => array(
'relation' => 'OR',
array( // Simple products type
'key' => '_sale_price',
'value' => 0,
'compare' => '>',
'type' => 'numeric'
),
array( // Variable products type
'key' => '_min_variation_sale_price',
'value' => 0,
'compare' => '>',
'type' => 'numeric'
)
)
);
query_posts( $args );
The code is placed in a copy of archive-product.php which I renamed archive-product_sale.php and made as a page template.
#gmaggio using query_posts() will break your site.
Use pre_get_posts
add_filter( 'pre_get_posts', 'catalog_filters' );
function catalog_filters( $query ) {
if ( $query->is_main_query() && $query->post_type = 'product' ) {
if(isset($_GET['onsale'])) {
$meta_query = array(
'relation' => 'OR',
array( // Simple products type
'key' => '_sale_price',
'value' => 0,
'compare' => '>',
'type' => 'numeric'
),
array( // Variable products type
'key' => '_min_variation_sale_price',
'value' => 0,
'compare' => '>',
'type' => 'numeric'
)
); $query->set('meta_query', $meta_query);
}
if(isset($_GET['bestsellers'])) {
$meta_query = array(
array(
'key' => 'total_sales',
'value' => 0,
'compare' => '>',
'type' => 'numeric'
)
);
}
}
return $query;
}
Create a new page using shortcode [sale_products per_page="12"]
List of available shortcodes and their parameters is here: http://docs.woothemes.com/document/woocommerce-shortcodes/
Solution for variable and simple products:
add_action( 'save_post_product', 'update_product_set_sale_cat_var' );
function update_product_set_sale_cat_var( $post_id ) {
$sales_ids = wc_get_product_ids_on_sale();
foreach ( $sales_ids as $sale_id ) :
if ($sale_id == $post_id) :
wp_set_object_terms($post_id, 'sale', 'product_cat', true );
else :
if ( has_term( 'sale', 'product_cat', $post_id ) ) {
wp_remove_object_terms( $post_id, 'sale', 'product_cat' );
}
endif;
endforeach;
}