0

I have an 'payments' meta_key for the users. I store the payment information (date and payment amount) received from the user in meta_value connected to this meta_key. For example:

array(
  [0] => array(
         'date' => '2020-04-15',
         'amount' => '750'
       ),
  [1] => array(
         'date' => '2020-04-20',
         'amount' => '900'
       )
)

I want to sort users by date of last payment in this meta_value. Example:

User 1 payments:

array(
  [0] => array(
         'date' => '2020-04-15',
         'amount' => '750'
       ),
  [1] => array(
         'date' => '2020-04-20',
         'amount' => '900'
       )
)

User 2 payments:

array(
  [0] => array(
         'date' => '2020-04-10',
         'amount' => '750'
       ),
  [1] => array(
         'date' => '2020-04-15',
         'amount' => '900'
       ),
  [2] => array(
         'date' => '2020-04-25',
         'amount' => '1250'
       )
)

User 3 payments:

array(
  [0] => array(
         'date' => '2020-04-24',
         'amount' => '750'
       )
)

Users List:

1- User 2
2- User 3
3- User 1

Is it possible to do this using the get_users function? I use this right now to list users:

$args = array(
    'meta_query' => array(
        array(
            'key' => 'payments',
            'value' => '',
            'compare' => '!='
        )
    ),
    'orderby' => 'display_name',
);
$users = get_users($args);

Note: Recent payments by users are always added to end of the array.

Sorry: Sorry for my bad English.

1

No, it's not possible to do this using the get_users function the way that you've outlined it, because get_users doesn't accept a meta_query argument the same way that get_posts does.

I see two approaches to get your desired result: either 1) get the users, then sort them afterwards, or 2) use $wpdb to write a direct database call. If you went that route, you'd want to be sure to cache the results using the transients API.

Option 1 route could be something like this:


<?php
// Assume that this is the data that we get back from get_users or a similar function
$users = array(
    0 => array(
        'name' => 'Tom',
        'payments' => array(
            0 => array(
                'date' => '2020-04-15',
                'amount' => '750',
            ),
            1 => array(
                'date' => '2020-04-20',
                'amount' => '900',
            ),
        ),
    ),
    1 => array(
        'name' => 'Dick',
        'payments' => array(
            0 => array(
                'date' => '2020-04-10',
                'amount' => '750',
            ),
            1 => array(
                'date' => '2020-04-15',
                'amount' => '900',
            ),
            2 => array(
                'date' => '2020-04-25',
                'amount' => '1250',
            ),
        ),
    ),
    2 => array(
        'name' => 'Harry',
        'payments' => array(
            0 => array(
                'date' => '2020-04-24',
                'amount' => '750',
            ),
        ),
    ),
);

function sort_users_by_date( $user1, $user2 ) {
    $date1 = end($user1['payments'])['date'];
    $date2 = end($user2['payments'])['date'];

    return strtotime($date1) - strtotime($date2);
}

usort($users, 'sort_users_by_date');

var_dump($users);

Demo

Using $wpdb is tricker. It'd go along these lines:

global $wpdb;
$users = $wpdb->get_results( 'SELECT * FROM {$wpdb->prefix}users INNER JOIN {$wpdb->prefix}usermeta ON {$wpdb->prefix}users.ID = {$wpdb->prefix}usermeta.user_id WHERE {$wpdb->prefix}usermeta.meta_key = "last_payment_date" ORDER BY {$wpdb->prefix}usermeta.meta_value DESC' );

This example assumes a couple of important things:

  1. You need to add another user meta key called "last_payment_date." Update this value when you add another payment to the user payments meta item. This way, you can query and order by a singular value, rather than going through the process of parsing an array inside an SQL statement.
  2. You should probably use $wpdb->prepare along with this. You can find documentation on that here.
| improve this answer | |
  • Sorry to respond late. Thank you for your help! – Faruk May 9 at 17:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.