I have a custom post type Archiv Kursunterlagen with some custom fields such as post_date. I want the posts of that post type to show in descending order by the custom field. I tried looking into other answers and modified the query. But it didn't work.
function my_pre_get_posts( $query ) {
// only modify queries for 'archive' post type
if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'archiv_kursunterlage' ) {
$query->set('orderby', 'meta_value');
$query->set('meta_key', 'post_date');
$query->set('order', 'DESC');
}
return $query;
}
add_action('pre_get_posts', 'my_pre_get_posts');
I have put this in a snippet and set it to run everywhere. Am I doing it right? or is there any problem with the query itself?
You can simply add the line in your code:
$query->set('order', 'DESC');
Please visit the link for more details:
https://www.advancedcustomfields.com/resources/orde-posts-by-custom-fields/
or
https://developer.wordpress.org/reference/hooks/pre_get_posts/
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;
}
hello I wanted to order articles post type by views count in wordpress. so I added a custom field to article post type which the name is view and it is a number field. I added it with PODS. I wrote this code in header.php so it it will incremenet automatically by each view:
<?php
if( get_post_type() == 'article' ) {
$postview = intval(get_post_field('views'));
if($postview > 0){
$postview = $postview+1;
}else{
$postview = 1;
}
$postID = $post->ID;
update_post_meta($postID,'views',$postview);
}
?>
it worked. but when I wanted to add a advanced query by elementor it does not work as expected. I added this to functions.php:
add_action( 'elementor/query/popular_articles', function( $query ) {
$query->set('post_type', 'article');
$query->set('meta_key', 'views');
$query->set('orderby', 'meta_value_num');
$query->set('order', 'DESC');
} );
I also tried this:
add_action( 'elementor/query/popular_articles', function( $query ) {
$query->set('orderby', 'views');
} );
none of those work as expected in elementor posts widget and the result is not sorted. when I set the popular_article query. the thing that I want to achieve with Wordpress WP_Query is something like this SQL query:
select post_title ,wp_z9gsc7_postmeta.meta_key,wp_z9gsc7_postmeta.meta_value from wp_z9gsc7_posts INNER JOIN wp_z9gsc7_postmeta ON wp_z9gsc7_posts.ID = wp_z9gsc7_postmeta.post_id where wp_z9gsc7_postmeta.meta_key = 'views' ORDER BY wp_z9gsc7_postmeta.meta_value DESC
thank you for your response in advance
this worked:
add_action( 'elementor/query/popular_articles', function( $query ) {
$query->set('post_type', 'article');
$query->set('meta_key', 'views');
$query->set('orderby', 'meta_value_num');
$query->set('order', 'DESC');
$query->set('offset', 0);
} );
I am trying to exclude certain posts from the Shop Order page e.g. '/wp-admin/edit.php?post_type=shop_order' if don't have a certain meta_key/meta_value combination present.
I have tried two approaches and neither seems to work properly:
Option 1: Pre Get Posts
add_action( 'pre_get_posts', 'so_filter_shop_order' );
function so_filter_shop_order($query) {
global $typenow;
/** #var $query WP_Query */
if ($query->is_main_query() && $typenow === 'shop_order' && is_admin()) {
$query->set( 'meta_key', '_method_created' );
$query->set( 'meta_value', 'booking' );
}
}
Limitations of Option 1 The problem with this option is that it doesn't seem to target other queries on this page (e.g. the count of different post statuses). I am also worried that this code will be targeting other queries elsewhere.
Option 2: Filter 'request'
This was an idea I got from WooCommerce CSV Export Plugin (as they filter this loop too).
add_filter( 'request', 'so_order_filters');
function so_order_filters( $vars ) {
global $typenow;
if ( 'shop_order' === $typenow ) {
$vars['meta_key'] = '_method_created';
$vars['meta_value'] = 'booking';
}
return $vars;
}
Limitations of Option 2 This approach also does not target other things on the page and it also conflicts with the CSV Export plugin because only one 'meta_key' can be added to the $vars array. I am also 95% sure this is not the right way to do it.
Where I would like help
It would be great to get some feedback on if either approach is worth pursuing or a suggested alternative please.
It would also be good to know if there are other things I can add to Option 1 to make sure it is only targeting the correct queries
Finally, any advice on how to target the other things on the other related queries on the page would be extremely useful.
Thanks in advance.
Here is another approach.
To get all post ID-s which has certain metakey+metavalue combination via SQL.
To include it with post__in parameter.
add_action( 'pre_get_posts', 'so_filter_shop_order' );
function so_filter_shop_order($query) {
global $wpdb;$excluded_results=array();
$excluded_results=$wpdb->query("select post_id from $wpdb->postmeta where meta_key='_method_created' and meta_value='booking' ");
foreach ($variable as $key => $value) {$excluded_results[]=$value;}
if (strpos($_SERVER["REQUEST_URI"],'post_type=shop_order') && is_admin()) {
$query->set( 'post__in', $excluded_results);
}
}
To affect table header part which shows the number of posts can't be done with pre_get_posts. It works through wp_count_posts filter. So you need to create a filter for this. Here is sample boilerplate for that:
add_filter('wp_count_posts','changenumbers',0,3);
function changenumbers ($counts, $type, $perm){
if (strpos($_SERVER["REQUEST_URI"],'post_type=product') && is_admin()) {
$counts->publish=0;
//var_dump($counts);
//you need to write some wp_query there which would get the number of posts by their status. Then you will only need to return those values.
}
return $counts;
}
when i add this code to my functions.php
function meta_filter_posts( $query )
{
if(is_tag() && is_main_query())
{
$currentTagId = get_queried_object()->term_id;
$query->set('orderby','meta_value_num');
$query->set('meta_key', 'rank_tag_'.$currentTagId.'');
$query->set('order', 'ASC');
}
}
add_filter( 'pre_get_posts', 'meta_filter_posts' );
my sidebar custom menu-widgets doesnt work anymore. The widgets show only the widget-title but not the widget-content.
The rest, e.g. the text-widgets are working normal.
But why? What is wrong with my code?
You have two problems here:
When using pre_get_posts, you should always make sure that you target the front end only. pre_get_posts alters all type of queries front end and backend
is_tag() and is_main_query() should be member variables of $query
You can do something like this
if(!is_admin() && $query->is_tag() && $query->is_main_query())
How can I hide posts from some category with some ID from main page of my site? I need solution like filter:
function exclude_post($query) {
if ($query->is_home) {
...
}
return $query;
}
add_filter('pre_get_posts', 'exclude_post');
Can somebody provide an example?
Use $query->set( $query_var, $value ); where $query_var is the variable you want to add/update in query. So put this inside your condition:
// 1st parameter is the query variable the 2nd is its value, in this case an array of category IDs
$query->set( 'category__not_in', array( 2, 6 ) );
Remember is good practice put in condition a check to $query->is_main_query(). pre_get_posts is an action hook so you have to change add_filter to add_action.
An action hook doesn't return a value, a filter does.
Example
function exclude_post( $query ) {
if ( $query->is_home() && $query->is_main_query() ) {
$query->set( 'category__not_in', array( 2, 6 ) );
}
}
add_action('pre_get_posts', 'exclude_post');
UPDATE
According to the new details emerging by the question,in order to exclude some posts in feeds stream, but not in category archive, the conditional check might look like:
if( $query->is_feed() && !$query->is_archive() )
OR
if( $query->is_feed() && !$query->is_category() )
Hope it helps!
you can also use the following way to exclude the a category from post query
<?php
if ( is_home() )
{
query_posts($query_string . '&cat=-3');
}
?>
You can use simple exclude in the query parameters :-
<?php wp_list_categories('orderby=name&show_count=1&exclude=10'); ?>
Its only sample , how to you exclude.
Hop it work..