Comment trier la zone d'administration d'un type de message personnalisé WordPress par un champ personnalisé

52

Lors de la modification de l'un de mes types de publication personnalisé, je souhaite pouvoir répertorier toutes les entrées selon un champ personnalisé au lieu de la date à laquelle elles sont publiées (ce qui, pour un type de publication personnalisé, n'est probablement pas pertinent). Les commentaires d'un article de blog sur les types d'articles personnalisés ont suscité l'intérêt des auteurs. L'auteur m'a dit que c'était possible et qu'il l'a même fait afin que vous puissiez cliquer sur les noms des colonnes pour un tri personnalisé. Il a mentionné la posts_orderbyfonction que j'avais notée dans mes propres commentaires, mais je peux maintenant retrouver le blog. Aucune suggestion? J'ai vu une solution qui utilisait

add_action('wp', 'check_page');

Et la check_pagefonction utilisée add_filterpour changer la requête mais je suis à peu près sûr que cela ne fonctionnerait que dans les fichiers de thème, pas dans la zone d'administration.

tooshel
la source
1
Voici une autre réponse utile, pour trier les messages par .... <br/> wordpress.stackexchange.com/questions/66455/…
T.Todua

Réponses:

66

Comme vous pouvez probablement l'imaginer par le manque de réponses fournies, la solution n'est pas vraiment triviale. Ce que j’ai fait est de créer un exemple assez autonome qui suppose un type de publication personnalisé de " movie" et une clé de champ personnalisée de " Genre ".

Avertissement : cela fonctionne avec WP3.0 mais je ne peux pas être sûr que cela fonctionnera avec les versions précédentes.

En gros, vous devez accrocher deux (2) crochets pour que cela fonctionne et deux autres (2) pour le rendre évident et utile.

Le premier point d'accroche est ' restrict_manage_posts', ce qui vous permet d'émettre un code HTML <select>dans la zone située au-dessus de la liste des publications où les filtres " Actions globales " et " Afficher les dates ". Le code fourni générera la fonctionnalité " Tri par: " comme indiqué dans cet extrait d'écran:

Comment créer la fonctionnalité Trier par pour un type de message personnalisé dans l'administrateur WordPress
(source: mikeschinkel.com )

Le code utilise le SQL direct car il n’existe pas de fonction API WordPress pour fournir la liste de toutes les méta_keys pour un type de publication (cela ressemble à un futur ticket de trac pour moi ...). Quoi qu’il en soit, voici le code. Notez qu’il saisit le type de message $_GETet le valide pour s’assurer qu’il s’agit à la fois d’un type de message valide post_type_exists()et d’un movietype de message (ces deux vérifications sont excessives, mais j’ai fait cela pour vous montrer comment, si vous ne voulez pas forcer.) code le type de post.) Enfin, j'utilise le sortbyparamètre URL car il n’est en conflit avec rien d’autre dans WordPress:

add_action('restrict_manage_posts','restrict_manage_movie_sort_by_genre');
function restrict_manage_movie_sort_by_genre() {
    if (isset($_GET['post_type'])) {
        $post_type = $_GET['post_type'];
        if (post_type_exists($post_type) && $post_type=='movie') {
            global $wpdb;
            $sql=<<<SQL
SELECT pm.meta_key FROM {$wpdb->postmeta} pm
INNER JOIN {$wpdb->posts} p ON p.ID=pm.post_id
WHERE p.post_type='movie' AND pm.meta_key='Genre'
GROUP BY pm.meta_key
ORDER BY pm.meta_key
SQL;
            $results = $wpdb->get_results($sql);
            $html = array();
            $html[] = "<select id=\"sortby\" name=\"sortby\">";
            $html[] = "<option value=\"None\">No Sort</option>";
            $this_sort = $_GET['sortby'];
            foreach($results as $meta_key) {
                $default = ($this_sort==$meta_key->meta_key ? ' selected="selected"' : '');
                $value = esc_attr($meta_key->meta_key);
                $html[] = "<option value=\"{$meta_key->meta_key}\"$default>{$value}</option>";
            }
            $html[] = "</select>";
            echo "Sort by: " . implode("\n",$html);
        }
    }
}

La deuxième étape requise consiste à utiliser le parse_queryhook appelé après que WordPress ait décidé quelle requête devrait être exécutée, mais avant de l'exécuter. Nous arrivons ici à définir les valeurs de orderbyet meta_keydans le query_vartableau de la requête qui sont documentées dans le Codex dans le orderbyparamètre for query_posts(). Nous testons pour nous assurer que:

  1. Nous sommes dans l'admin ( is_admin()),
  2. Nous sommes sur la page qui répertorie les messages dans le admin ( $pagenow=='edit.php'),
  3. La page a été appelée avec un post_typeparamètre d'URL égal à movie, et
  4. La page a également été appelée avec un sortbyparamètre d'URL et la valeur " Aucune " n'a pas été transmise .

Si tous ces tests réussissent, nous définissons le query_vars(comme indiqué ici ) sur meta_valueet notre sortbyvaleur pour ' Genre ':

add_filter( 'parse_query', 'sort_movie_by_meta_value' );
function sort_movie_by_meta_value($query) {
    global $pagenow;
    if (is_admin() && $pagenow=='edit.php' &&
        isset($_GET['post_type']) && $_GET['post_type']=='movie' && 
        isset($_GET['sortby'])  && $_GET['sortby'] !='None')  {
        $query->query_vars['orderby'] = 'meta_value';
        $query->query_vars['meta_key'] = $_GET['sortby'];
    }
}

Et c'est tout ce que vous devez faire. pas de crochets " posts_order" ou " wp" requis! Bien sûr, vous devez en faire plus. vous devez ajouter sur votre page des colonnes qui répertorient les publications pour que vous puissiez réellement voir les valeurs qu’elle trie, sans quoi les utilisateurs perdraient leur confusion. Alors ajoutez un manage_{$post_type}_posts_columnscrochet, dans ce cas manage_movie_posts_columns. Ce hook reçoit le tableau de colonnes par défaut et, pour des raisons de simplicité, je viens de le remplacer par deux colonnes standard; une case à cocher ( cb) et un nom de poste ( title). (Vous pouvez inspecter posts_columnsavec a print_r()pour voir ce qui est disponible par défaut.)

J'ai décidé d'ajouter un " Tri par: " pour quand il y a un sortbyparamètre d'URL et quand il ne l'est pas None:

add_action('manage_movie_posts_columns', 'manage_movie_posts_columns');
function manage_movie_posts_columns($posts_columns) {
    $posts_columns = array(
        'cb' => $posts_columns['cb'],
        'title' => 'Movie Name',
        );
    if (isset($_GET['sortby']) && $_GET['sortby'] !='None') 
        $posts_columns['meta_value'] = 'Sorted By';

    return $posts_columns;
}

Enfin, nous utilisons le manage_pages_custom_columncrochet pour afficher la valeur s’il existe une publication du type de publication approprié et avec le test probablement redondant pour is_admin()et $pagenow=='edit.php'. Lorsqu'il existe un sortbyparamètre d'URL, nous extrayons la valeur du champ personnalisé en cours de tri en la affichant dans notre liste. Voici à quoi ça ressemble (rappelez-vous, ce sont des données de test, donc pas de commentaire de la galerie Peanut sur les classifications de films! :):

Colonnes personnalisées ajoutées pour un type de publication personnalisé dans l'administrateur WordPress
(source: mikeschinkel.com )

Et voici le code:

add_action('manage_pages_custom_column', 'manage_movie_pages_custom_column',10,2);
function manage_movie_pages_custom_column($column_name,$post_id) {
    global $pagenow;
    $post = get_post($post_id);
    if ($post->post_type=='movie' && is_admin() && $pagenow=='edit.php')  {
        switch ($column_name) {
            case 'meta_value':
                if (isset($_GET['sortby']) && $_GET['sortby'] !='None') {
                    echo get_post_meta($post_id,$_GET['sortby'],true);
                }
                break;
        }
    }
}

Notez que cela ne prend que le premier " Genre " pour un movie, c'est-à-dire la première méta_value dans le cas de valeurs multiples pour une clé donnée. Mais là encore, je ne suis pas sûr de savoir comment cela fonctionnerait autrement!

Et pour ceux qui ne savent pas où placer ce code, vous pouvez le mettre dans un plugin ou plus vraisemblablement pour le novice dans le functions.phpfichier de votre thème actuel.

Comment cela aide.

Mike Schinkel
la source
2
+1, juste pour l'effort. Mais ce serait encore mieux si les cercles étaient dessinés à la main :-)
Jan Fabry
Avez-vous une idée de la façon de supprimer complètement le filtre SHOW ALL DATES de sorte que seuls mes filtres personnalisés apparaissent pour un type de publication donné?
RailsTweeter
@RailsTweeter Utilisez la technique que j'ai montrée ici où les deux crochets qui relient la génération HTML sont 'months_dropdown_results'et 'restrict_manage_posts'. PS Les votes positifs sont toujours appréciés. :)
MikeSchinkel
@MikeSchinkel, maintenant qu'il existe une API WP, cela mettra-t-il votre code à jour?
Samjco
@samjco Pas sûr. Je n'ai malheureusement pas le temps de réviser cela pour le moment.
MikeSchinkel
-1

Voici une solution simple:

/* --------Sortable Events on Dashboard - show start date, time, venue--------- */

/*-------------------------------------------------------------------------------
    Custom Columns
-------------------------------------------------------------------------------*/

function my_*YOUR POST TYPE*_columns($columns)
{
    $columns = array(
        'cb'        => '<input type="checkbox" />',
        'title'     => 'Title',
        'your_custom_field'     => 'Custom Field Name',          
        'date'      =>  'Date',
    );
    return $columns;
}

function my_custom_columns($column)
{
    global $post;
    if($column == 'your_custom_field')
    {
        if(get_post_meta($post->ID, 'your_custom_field', true);)
        {
            echo get_post_meta($post->ID, 'your_custom_field', true);
        }
    }

}

add_action("manage_posts_custom_column", "my_custom_columns");
add_filter("manage_edit-*YOUR POST TYPE*_columns", "my_events_columns");

/*-------------------------------------------------------------------------------
    Sortable Columns
-------------------------------------------------------------------------------*/

function my_column_register_sortable( $columns )
{
    $columns['your_custom_field'] = 'your_custom_field';
    return $columns;
}

add_filter("manage_edit-*YOUR POST TYPE*_sortable_columns", "my_column_register_sortable" );

Il suffit de remplacer VOTRE TYPE DE POSTE et 'your_custom_field'

Jake
la source