¿Cómo ordenar los resultados de WP_User_Query para que coincidan con el orden de una matriz de ID de usuario?

2

Estoy usando WP_User_Query para obtener una lista de usuarios de mi base de datos. Estoy mostrando usuarios específicos solo mediante el uso del parámetro include . Por ejemplo:

$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 />';
}

Los resultados están ordenados actualmente por user_login . Mi objetivo es ordenar los resultados por los ID de usuario utilizados en el parámetro include . Entonces, por ejemplo, si se deben devolver 5 usuarios (digamos las ID de usuario 1, 5, 99, 61 y 12), entonces necesito el bucle foreach para generar resultados en este orden:

1
5
99
61
12

Tenga en cuenta He intentado usar usort() después de que se ejecutó la consulta (consulte here ), pero ahora necesito que se ordenen los resultados reales de la consulta. No deseo ordenar los resultados de la consulta después de que se haya ejecutado la consulta.

Ref: enlace

    
pregunta henrywright 31.10.2014 - 16:52

2 respuestas

5

Actualizado:

La clase WP_User_Query , en WordPress 4.1+, la admite con:

'orderby' => 'include'

Desde WordPress 4.7 también hay soporte para:

'orderby' => 'login__in'

y

'orderby' => 'nicename__in'

Por lo tanto, ya no necesitamos implementarlo a través de un filtro, como hicimos a continuación.

Respuesta anterior:

Me pregunto si esto funciona para ti:

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' )

donde

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 . ' )';         
    }
}

utilizando la función FIELD() en MySQL. Hay algunos ejemplos de uso aquí en los comentarios de la página de documentación de MySQL.

Actualizar:

Para hacerlo más flexible, podríamos usar este mini complemento:

/**
 * 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 . ' )';
    }

});

donde usamos el prefijo de subrayado _include , en caso de que el núcleo use el valor include en el futuro. Actualización : He ajustado esto para que ahora sea más o menos similar al caso de pedido post__in de la clase WP_Query .

Ahora puedes simplemente usar:

$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 );

para ordenar por el include array.

    
respondido por el birgire 31.10.2014 - 17:17
1

Una alternativa ofrecida a la respuesta anterior es agregar una columna (clave de metadatos) con valores meta que pueden ordenarse fácilmente con 'orderby' => 'meta_value' en los argumentos.

Aquí hay una función que escribí para agregar los valores meta a cada usuario. Lo incluyo aquí porque $my_order_ids = array( 3, 4, 6, 2, 5 ); determina el orden ascendente que los usuarios deben ordenar en su consulta.

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' );

Esto utiliza un bucle foreach para agregar un nuevo valor entero a la clave my_user_order de cada usuario, incrementándose en 1 cada vez. Todo lo que necesita hacer es definir $my_order_ids en el orden en que desea que se ordenen más adelante.

El transitorio está justo ahí, de modo que las actualizaciones solo se ejecutarán cuando los valores de $my_order_ids hayan cambiado (en otras palabras, solo actualizar a los usuarios una vez). Es posible que desee comentar add_action( 'admin_notices', 'my_order_column' ); para evitar que se ejecute inesperadamente si se pierde el transitorio.

Ahora que hemos establecido nuestra nueva meta clave y nuestros valores meta, no deberíamos tener problemas para que la consulta los ordene de esta manera.

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' );

En el ejemplo anterior, la siguiente salida se muestra como un aviso de administración:

3
4
6
2
5
    
respondido por el iyrin 03.11.2014 - 09:20

Lea otras preguntas en las etiquetas