web-dev-qa-db-fra.com

Comment faire pour que les résultats de WP_User_Query correspondent à l'ordre d'un tableau d'ID utilisateur?

J'utilise WP_User_Query pour obtenir une liste d'utilisateurs de ma base de données. Je montre des utilisateurs spécifiques uniquement via le paramètre include. Par exemple:

$args = array(
    'include' => array( 1, 3, 5, 99, 61, 24, 12 ),
    'count_total' => true,
    'search' => sanitize_text_field( $_GET['phrase'] )
);

$query = new WP_User_Query( $args );
foreach( $query->results as $user ) {
    echo $user->ID . '<br />';
}

Les résultats sont actuellement classés par user_login. Mon objectif est de classer les résultats en fonction des ID utilisateur utilisés dans le paramètre include. Ainsi, par exemple, si 5 utilisateurs doivent être renvoyés (par exemple, les ID d’utilisateur 1, 5, 99, 61 et 12), il me faut alors la boucle foreach pour obtenir les résultats dans cet ordre:

1
5
99
61
12

Remarque J'ai essayé d'utiliser usort() après l'exécution de la requête (voir ici ), mais maintenant. J'ai besoin que les résultats de la requête soient commandés. Je ne souhaite pas commander les résultats de la requête une fois celle-ci exécutée.

Réf: http://codex.wordpress.org/Class_Reference/WP_User_Query

2
henrywright

Mise à jour:

La classe WP_User_Query, dans WordPress 4.1+, la supporte avec:

'orderby' => 'include'

Depuis WordPress 4.7, il existe également un support pour:

'orderby' => 'login__in'

et

'orderby' => 'nicename__in'

Nous n’avons donc plus besoin de l’implémenter par le biais d’un filtre, comme nous l’avons fait ci-dessous.

Réponse précédente:

Je me demande si cela fonctionne pour vous:

add_action( 'pre_user_query', 'wpse_order_by_include_values' )
$query = new WP_User_Query( $args );
remove_action( 'pre_user_query', 'wpse_order_by_include_values' )

function wpse_order_by_include_values( $q )
{
    if( isset( $q->query_vars['include'] ) )
    {
        $values = join( ',', $q->query_vars['include'] );
        $q->query_orderby = 'ORDER BY FIELD( ID,' . $values . ' )';         
    }
}

en utilisant la fonction FIELD() dans MySQL. Il y a quelques exemples d'utilisation ici dans les commentaires de la page doc de MySQL.

Mise à jour:

Pour le rendre plus flexible, nous pourrions utiliser ce mini plugin:

/**
 * Support the 'orderby' => '_include' parameter for the WP_User_Query 
 * to order by the values in the include array.
 * 
 * @see http://wordpress.stackexchange.com/a/167095/26350
 */

add_action( 'pre_user_query', function( $q ) {

    if( 
        isset( $q->query_vars['orderby'] )
        && '_include' === $q->query_vars['orderby']
        && isset( $q->query_vars['include'] ) 
        && count( $q->query_vars['include'] ) > 0 
    )
    {
        global $wpdb;
        $users_in = join( ',', array_map( 'absint', $q->query_vars['include'] ) );
        $q->query_orderby = 'ORDER BY FIELD( {$wpdb->users}.ID,' . $users_in . ' )';
    }

});

où nous utilisons le préfixe de soulignement _include, juste au cas où le noyau utilisera la valeur include dans le futur. Mise à jour : J'ai ajusté ceci afin qu'il ressemble plus ou moins au cas de classement post__in de la classe WP_Query.

Maintenant, vous pouvez simplement utiliser:

$args = array(
    'include'     => array( 1, 3, 5, 99, 61, 24, 12 ),
    'count_total' => true,
    'search'      => sanitize_text_field( $_GET['phrase'] )
    'orderby'     => '_include',                               //<-- our new value
);

$query = new WP_User_Query( $args );

commander par le tableau include.

5
birgire

Une alternative à la réponse ci-dessus consiste à ajouter une colonne (clé méta) avec des valeurs méta qui peuvent facilement être triées avec 'orderby' => 'meta_value' dans les arguments.

Voici une fonction que j'ai écrite pour ajouter les méta-valeurs à chaque utilisateur. Je l’inclus ici car $my_order_ids = array( 3, 4, 6, 2, 5 ); détermine l’ordre croissant dans lequel les utilisateurs doivent être triés dans votre requête.

function my_order_column() {
// Defines the user IDs to be updated.
// Use the desired order when you define this.
$my_order_ids = array( 3, 4, 6, 2, 5 );

    // Runs only when $my_order_ids has changed by comparing  
    // it to _transient_my_order_column. 
    if (false === get_transient('my_order_column') ||
        get_transient('my_order_column') !== $my_order_ids) {

        // Updates _transient_my_order_column
        set_transient('my_order_column', $my_order_ids);

        // The first user
        $order_id = 1;
        // Add an integer value for each user 
        foreach ($my_order_ids as $user_id) {

        // Sets/updates the value of my_user_order
        update_user_meta( $user_id, 'my_user_order', $order_id );

        // Confirms that the new value of my_user_order matches the 
        // current value of $order_id
        if ( get_user_meta($user_id,  'my_user_order', true ) != $order_id )
            wp_die('An error occurred');

            $order_id++;
        }
    ?><div class="updated">
        <p><?php echo var_dump($my_order_ids) . '<br />Updated!'; ?></p>
    </div><?php
    }
}

add_action( 'admin_notices', 'my_order_column' );

Ceci utilise une boucle foreach pour ajouter une nouvelle valeur entière à la clé my_user_order de chaque utilisateur, incrémentant de 1 à chaque fois. Tout ce que vous avez à faire est de définir $my_order_ids dans l'ordre de tri souhaité.

Le transitoire est juste là pour que les mises à jour ne s'exécutent que lorsque les valeurs de $my_order_ids ont changé (en d'autres termes, ne mettez à jour les utilisateurs qu'une seule fois). Vous souhaiterez peut-être commenter add_action( 'admin_notices', 'my_order_column' ); pour l'empêcher de fonctionner de manière inattendue si le transitoire est perdu.

Maintenant que notre nouvelle clé méta personnalisée et nos méta valeurs sont définies, nous ne devrions plus avoir de difficulté à obtenir la requête pour les commander de cette manière.

function my_user_query() {

$args = array(
    'orderby' => 'meta_value',     /***************************************/
    'order' => 'ASC',              /***Added orderby, order and meta_key***/
    'meta_key' => 'my_user_order', /***************************************/
    // Note: 'include' does not affect how output will be ordered. 
    // array( 6, 5, 3, 2, 4 ) would still be ordered by meta_value.
    'include' => array( 3, 4, 6, 2, 5 ),
    'count_total' => true,
    'search' => sanitize_text_field( $_GET['phrase'] )
);

$query = new WP_User_Query( $args );

    ?>
    <div class="updated">
        <p><?php foreach( $query->results as $user ) {
        echo $user->ID . '<br />'; } ?></p>
    </div>
    <?php  wp_reset_query();
}

add_action( 'admin_notices', 'my_user_query' );

Dans l'exemple ci-dessus, la sortie suivante est affichée en tant qu'avis d'administration:

3
4
6
2
5
1
iyrin