I am trying to modify all queries of a post type "products" to only show if the product/post has a certain meta_key of "wholesale_price" which the meta_value needs to be greater than 0.
Here is what i have:
add_action( 'pre_get_posts', 'rc_modify_query_get_design_projects' );
function rc_modify_query_get_design_projects( $query ) {
if($query->is_main_query() && $query->query_vars['post_type'] == 'product' ) {
$query->set('meta_key', 'wholesale_price');
$query->set('meta_compare', '>');
$query->set('meta_value', '0');
}
}
For some reason this still returns everything. Is this the right way of doing things?
The problem is the method by which you are setting your meta_query. You should read up on the WP_Query functionality, because meta queries are unfortunately not that simple.
You need to do something more like so:
add_action( 'pre_get_posts', 'rc_modify_query_get_design_projects' );
function rc_modify_query_get_design_projects( $query ) {
// Do not add meta arguments in admin pages
if (is_admin()) {
return;
}
if($query->is_main_query() && $query->query_vars['post_type'] == 'product' ) {
//Get original meta query
$meta_query = (array)$query->get('meta_query');
// Add your criteria
$meta_query[] = array(
'key' => 'wholesale_price',
'value' => 0,
'compare' => '>',
);
// Set the meta query to the complete, altered query
$query->set('meta_query',$meta_query);
}
And no need to return anything in this function.
Related
I want to display my woocommerce products on two different sections on the site i.e. the shop page and on an archive page i created using Custom Post UI plugin, called artists.
Using the Advanced Custom Fields plugin, i created a field that will attach each product created to an individual artist. The plan now is, on each artist page, pull products for the artist.
This is what i have so far. I hook into woocommerce_product_query, check if i'm on the single artist page and implement my meta query:
function artist_products( $query )
{
if( is_singular('artists') )
{
$meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];
$meta_query[] = array(
'key' => '_fld_select_artist',
'value' => get_the_ID(),
);
$query->set( 'meta_query', $meta_query );
}
}
add_action( 'woocommerce_product_query', 'artist_products' );
This is not working. When i visit my single artist page, i get a 500 server error. What I'm i missing?
woocommerce_product_query was breaking my site for some reason so i switched to pre_get_posts:
function artist_products( $query )
{
if ( $query->get('post_type') == 'nav_menu_item' )
{
return $query;
}
if( ! is_admin() && is_singular('artists') )
{
$meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];
$meta_query[] = array(
'key' => '_fld_select_artist',
'value' => get_the_ID(),
'compare' => '=',
);
$query->set( 'meta_query', $meta_query );
}
}
add_action( 'pre_get_posts', 'artist_products' );
I'm trying to update the sorting of search results in wordpress / woocommerce
so, when there is a search as: mydomain.com/?s=cases&post_type=product
The results get sorted by the 'total_sale' meta_key
I have the following hook
function sv_update_default_search_to_sales( $query ){
// check if the user is requesting an admin page
// or current query is not the main query
if ( is_admin() || ! $query->is_main_query() ){
return;
}
// Query Update for Search Results pages with products
if (is_search() && is_woocommerce() ){
if(get_query_var('post_type') != 'product'){
return;
}
$orderBy = get_query_var('orderby');
if(empty($orderBy) || $orderBy == 'relevance'){
$query->set('orderby', 'meta_value_num');
$query->set('order', 'desc');
$query->set('meta_key', 'total_sales');
$query->set('meta_type', 'NUMERIC');
}
}
}
add_action( 'pre_get_posts', 'sv_update_default_search_to_sales', 1 );
When I output $wp_query after the query has been parsed, i can see the 'meta_key' has been set to blank.
[meta_key] =>
[orderby] => meta_value_num
[order] => DESC
[meta_type] => NUMERIC
I've seen on other codes examples where they set meta_key and meta_value for matching; however, i don't have a set value, i need to order the results by 'total_sales' meta key.
Im basically trying to recreate this type of query call:
$query = new WP_Query([
'post_type' => 'product',
'meta_key' => 'total_sales',
'orderby' => 'meta_value_num'
]);
OK, so after further debugging. I realized there were other plugins modifying the query that were set to fire after my action.
I don't know which plugin specifically was modifying it, but after the page is rendered I printed the filter with
global $wp_filter;
echo '<pre>';
print_r($wp_filter['pre_get_posts']);
echo '</pre>';
Figured outthe action number: 90000 was the last action hooked, so I set mines to 90001
add_action( 'pre_get_posts', 'sv_update_default_search_to_sales', 900001 );
and it worked! x)
I would like to query my posts by filtering for a custom meta added with Advanced Custom Fields. It's a boolean meta, so every post will have something like:
GET http://localhost/wp-json/wp/v2/posts
{
...
"acf" : {
"highlight" : true
}
...
}
I'm not able to filter by this meta value, even if I exposed meta_key and meta_value to the REST API in function.php:
function my_add_meta_vars ($current_vars) {
$current_vars = array_merge ($current_vars, array ('meta_key', 'meta_value'));
return $current_vars;
}
add_filter ('rest_query_vars', 'my_add_meta_vars');
But if I try:
GET
http://localhost/wp-json/wp/v2/posts?filter[meta_key]=highlight&filter[meta_value]=true
I see all the posts as if the filter is ignored.
I was able to get this solved with this customization:
add_filter( 'rest_query_vars', function ( $valid_vars ) {
return array_merge( $valid_vars, array( 'highlight', 'meta_query' ) );
} );
add_filter( 'rest_post_query', function( $args, $request ) {
$highlight = $request->get_param( 'highlight' );
if ( ! empty( $highlight ) ) {
$args['meta_query'] = array(
array(
'key' => 'highlight',
'value' => $highlight,
'compare' => '=',
)
);
}
return $args;
}, 10, 2 );
And do a query in this way (highlight is acf boolean)
GET /wp-json/wp/v2/posts?highlight=1
I'm trying to automatically exclude all articles that don't have a custom field set. I have checked the 'instant_articles_before_render_post' and 'instant_articles_after_render_post' hooks but I wonder how I could use them to prevent the render of the article. Any ideas?
instant_articles_before_render_post and instant_articles_after_render_post are used to launch actions before / after the post rendering but cannot prevent the post to render. What you need to do is to hook on pre_get_posts in order to change the main query used by Facebook Instant Articles.
If you look in the facebook-instant-articles.php plugin file, you will see the following function:
function instant_articles_query( $query ) {
if ( $query->is_main_query() && $query->is_feed( INSTANT_ARTICLES_SLUG ) ) {
$query->set( 'orderby', 'modified' );
$query->set( 'posts_per_page', 100 );
$query->set( 'posts_per_rss', 100 );
/**
* If the constant INSTANT_ARTICLES_LIMIT_POSTS is set to true, we will limit the feed
* to only include posts which are modified within the last 24 hours.
* Facebook will initially need 100 posts to pass the review, but will only update
* already imported articles if they are modified within the last 24 hours.
*/
if ( defined( 'INSTANT_ARTICLES_LIMIT_POSTS' ) && INSTANT_ARTICLES_LIMIT_POSTS ) {
$query->set( 'date_query', array(
array(
'column' => 'post_modified',
'after' => '1 day ago',
),
) );
}
}
}
add_action( 'pre_get_posts', 'instant_articles_query', 10, 1 );
You can hook right after this and add your own meta condition like this:
function instant_articles_query_modified($query) {
if($query->is_main_query() && isset(INSTANT_ARTICLES_SLUG) && $query->is_feed(INSTANT_ARTICLES_SLUG)) {
$query->set('meta_query', array(
array(
'key' => 'your_required_meta'
)
));
}
add_action('pre_get_posts', 'instant_articles_query_modified', 10, 2);
Thanks. The code above didn't quite work because it's missing a closing } and the isset caused a problem.
Try this:
function instant_articles_query_modified($query) {
if($query->is_main_query() && null!==INSTANT_ARTICLES_SLUG && $query->is_feed(INSTANT_ARTICLES_SLUG)) {
$query->set('meta_query', array(
array(
'key' => 'your_required_meta'
)
));
}
}
I have a situation where I have a query with two different post types and I have to checkboxes on top with the names of post type. I wont by default those checkboxes to be checked and if one of theme is unchecked to remove that post type and the post affiliated to that post type from the query.
This part is circumstancial, but you get the idea. Give the values to the ones that are/aren't checked.
if($checkboxone == '1') {
$types = array( 'typeone' )
}
if($checkboxtwo == '1') {
$types = array( 'typetwo' )
}
if($checkboxtwo == '1' && $checkboxone == '1'){
$types = array( 'typeone', 'typetwo' )
}
then plug that value into your WP_Query by some means like this. the documentation for it is here
// The Query
$the_query = new WP_Query( array( 'post_type' => $types );
// The Loop
while ( $the_query->have_posts() ) : $the_query->the_post();
//DO STUFF
endwhile;
// Reset Post Data
wp_reset_postdata();