web-dev-qa-db-fra.com

Triez la table de liste de types de publication personnalisée en fonction du nom d'affichage d'un ID utilisateur stocké en tant que méta valeur de publication.

J'ai un type de message personnalisé nommé domicile. Chaque poste (domicile) a un propriétaire (pas le auteur ). Les propriétaires sont des utilisateurs dotés d'un rôle personnalisé. Je stocke l'ID utilisateur sous la forme d'une méta valeur (dmb_owner) pour le type de message domicile.

Comment trier la liste (wp-admin/edit.php?post_type=domicile) par les noms d'affichage des propriétaires?

Le code correspondant de ma classe, setup_columns(), est appelé le init:

/**
 * Manage columns for List Table.
 *
 * @wp-hook init
 * @return void
 */
protected function setup_columns()
{
    add_filter(
        "manage_edit-{$this->post_type}_columns",
        array ( $this, 'set_column_header' )
    );

    add_action(
        "manage_{$this->post_type}_posts_custom_column",
        array ( $this, 'render_columns' ),
        10,
        2
    );

    add_filter(
        "manage_edit-{$this->post_type}_sortable_columns",
        array ( $this, 'set_sortable_columns' )
    );

    add_filter(
        'request',
        array ( $this, 'prepare_orderby' )
    );
}

/**
 * Register column headers.
 *
 * @wp-hook manage_edit-{$this->post_type}_columns
 * @param  array $columns
 * @return array
 */
public function set_column_header( $columns )
{
    unset (
        $columns['author'],
        $columns['comments'],
        $columns['date']
    );
    $columns['owner'] = __( 'Owner', 't5_domicile_manager' );

    return $columns;
}

/**
 * Display cell content.
 *
 * @wp-hook manage_{$this->post_type}_posts_custom_column
 * @param string $column_name
 * @param int $post_id
 * @return void
 */
public function render_columns( $column_name, $post_id = 0 )
{
    if ( 'owner' === $column_name )
    {
        $owner_id = get_post_meta( $post_id, 'dmb_owner', TRUE );
        if ( $owner_id )
        {
            $owner = get_user_by( 'id', $owner_id );
            print $owner ? $owner->display_name : '<i>not set</i>';
        }
    }
}

/**
 * Register sortable columns
 *
 * @wp-hook manage_edit-{$this->post_type}_sortable_columns
 * @param array $columns
 * @return array
 */
public function set_sortable_columns( $columns )
{
    $columns['owner'] = 'owner';
    return $columns;
}

/**
 * Set custom sort order.
 *
 * @wp-hook request
 * @param  array $vars
 * @return array
 */
public function prepare_orderby( $vars )
{
    if ( isset ( $vars['orderby'] ) && 'owner' == $vars['orderby'] )
    {
        $vars = array_merge(
            $vars,
            array (
                'meta_key' => 'dmb_owner',
                'orderby'  => 'meta_value_num'
            )
        );
    }
    return $vars;
}

Cela… fonctionne, mais c'est évidemment faux, car cela trie par ID stocké. Je dois filtrer la requête - mais je ne sais pas exactement comment je devrais le faire.

Désolé pour le titre, mais je veux m'assurer qu'il sera trouvé. J'ai cherché très fort et je n'ai rien trouvé d'utile.

5
fuxia

Une solution 'facile' mais pas très bonne consiste à stocker le nom d'affichage ainsi que l'ID de l'utilisateur et à les trier. Évidemment, une mise à jour du nom d'affichage d'un utilisateur demanderait une mise à jour de tout le domicile que possède l'utilisateur.

Alternativement, ce qui suit est un aperçu (non testé) de ce qui devrait fonctionner. L'idée est de dire à WordPress de trier toujours la méta-valeur (pour que WordPress rejoigne la table meta) et qu'il est ensuite possible d'utiliser le filtre post_clauses pour rejoindre la table users et trier par nom complet:

add_filter('posts_clauses', 'wpse58638_post_clauses',10,2);
function wpse58638_post_clauses( $clauses, $query ) {
    global $wpdb;
    if ( ! $query->is_main_query()
        || ! is_admin()
        || ! $query->get('post_type') == 'domicile'
        || ! $query->get('meta_key') == 'dmb_owner'
        || ! $query->get('orderby') == 'meta_value_num'
    ){
        return $clauses;
    }

    //Get sort order
    $order_dir = $query->get('order');
    $order_dir = ('asc' == $order_dir ? 'ASC' : 'DESC');

    //Join user table onto the postmeta table
    $clauses['join'] .= " LEFT JOIN {$wpdb->users} ON {$wpdb->prefix}postmeta.meta_value={$wpdb->users}.ID";

    //Replace orderby
    $clauses['orderby']  = " {$wpdb->users}.display_name $order_dir";

    return $clauses;
}
7
Stephen Harris

Vous pouvez ajouter le champ personnalisé dmb_owner à la requête dans le backend, puis filtrer à ce sujet avec vos filtres standard.

add_filter( 'query_vars', 'fb_query_vars_admin' );
/**
 * If needed: Allow meta queries in the admin
 */
function fb_query_vars_admin( $query_vars ) {

    // break off, if not in admin area
    if ( ! is_admin() )
        return $query_vars;

    $query_vars[] = 'dmb_owner'; // my key of custom field
    //$query_vars[] = 'meta_value'; // my value of custom field

    return $query_vars;
}

Ce champ personnalisé se trouve maintenant dans le $query_vars et peut être utilisé, comme votre méthode prepare_orderby().

0
bueltge