4

I adapted a little a function to display a number of random users with their avatars with a shortcode. It works, but something is not good. Sometimes it displays with one user less than I want (just a blank line instead of the first user), sometimes it includes the administrator, although it should not. What is wrong with my code?

add_shortcode( 'random_users', 'display_random_users' );
//Usage: [random_users how_many = 3]

function display_random_users( $atts ) {

    extract(shortcode_atts( array( "how_many" => '' ), $atts ) );

    $args = array(
        'orderby' => 'ID',
        'role' => 'subscriber',
        'fields' => 'ID'
    );

    $users = get_users( $args );
    $users = array_rand( $users, $how_many );

    foreach ( $users as $userID ) {
        echo '<a href="' . 
            bp_core_get_user_domain( $userID ) . '">' . 
            bp_core_fetch_avatar( array( 'item_id' => $userID ) ) . '<br />' . 
            xprofile_get_field_data( '1', $userID ) . '</a><br />';
    }
}
2
  • Do a print_r($users) to see what your query is returning. That way you can make sure you're only getting subscribers, not admins. Also, does get_users not support orderby=rand? I know wp_query does, but not sure about get_users. If it does, it would be easier to only query the amount of users in $how_many instead.
    – gdaniel
    Jan 6, 2015 at 22:16
  • @gdaniel This is what returned the print_r($users): Array ( [0] => 0 [1] => 1 [2] => 23 ). So, the first user is inexistent and the second is the admin, right?
    – Yurié
    Jan 6, 2015 at 22:30

1 Answer 1

5

I am not sure why your query is returning more IDs than necessary. The $args for get_users look correct.

By default get_users does not support orderby=rand, but you can overwrite that option. See below:

function random_user_query( &$query )
{
    $query->query_orderby = "ORDER BY RAND()";
}

// Usage: [random_users how_many = 3]
add_shortcode( 'random_users', 'display_random_users' );
function display_random_users( $atts ) {

    shortcode_atts( array( "how_many" => '', ), $atts );

    // Create a function to override the ORDER BY clause
    add_action( 'pre_user_query', 'random_user_query' );

    $users = get_users( array(
        'role'    => 'subscriber',
        'fields'  => 'ID',
        'orderby' => 'rand',
        'number'  => $atts['how_many'],
    ) );

    foreach ( $users as $userID ) {
        printf( 
            '<a href="%s">%s<br />%s</a><br />',
            bp_core_get_user_domain( $userID ),
            bp_core_fetch_avatar( array( 'item_id' => $userID ) ),
            xprofile_get_field_data( '1', $userID )
        );
    }

    // Remove the hook
    remove_action( 'pre_user_query', 'random_user_query' );
}

This way, you only query $how_many users, instead of querying all users and then filtering out $how_many.

I found this hook here.

6
  • The orderby in $args must appear twice? However, it seems that the function works well. Thank you!
    – Yurié
    Jan 6, 2015 at 22:52
  • I think the 'orderby' => 'ID' is not nedeed, so I removed it.
    – Yurié
    Jan 6, 2015 at 23:05
  • 2
    It was not needed, I missed that. I removed it.
    – gdaniel
    Jan 6, 2015 at 23:55
  • As PHP 5.2 and anonymous functions are gone now with 5.3 dead (see those stats about secure versions), I'd suggest to use a Closure: add_action( 'pre_user_query', function( $q ) { ... } ); instead. Anyway, +1 for the answer :)
    – kaiser
    Jan 7, 2015 at 0:03
  • 1
    I hope you don't mind the edit. Else removing the action wouldn't have been possible. More info about that problem in this answer and in this answer.
    – kaiser
    Jan 7, 2015 at 15:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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