web-dev-qa-db-fra.com

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

Lors de la modification de l'un de mes types de publication personnalisés, 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 et l'auteur m'a dit que c'était possible et qu'il l'a même fait pour que vous puissiez cliquer sur les noms des colonnes pour un tri personnalisé. Il a mentionné la fonction posts_orderby 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 fonction check_page utilisée add_filter pour modifier la requête, mais je suis à peu près sûre que cela ne fonctionnerait que dans les fichiers de thème, pas dans la zone d'administration.

52
tooshel

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".

Disclaimer _ : 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'accrochage est 'restrict_manage_posts' qui vous permet d'émettre un <select> HTML dans la zone située au-dessus de la liste des publications contenant les filtres "actions globales _" et "Afficher les dates}". Le code fourni générera la fonctionnalité "Trier par: _" comme indiqué dans l'extrait d'écran suivant:

 How to Create Sort By functionality for a Custom Post Type in the WordPress Admin 
(source: mikeschinkel.com )

Le code utilise SQL direct car il n’existe pas de fonction API WordPress pour fournir la liste de toutes les méta_keys d’un type de publication (sonne comme un futur trac ticket pour moi ...). Quoi qu’il en soit, voici le code. Notez qu’il saisit le type de message à partir de $_GET et le valide pour s’assurer qu’il s’agit à la fois d’un type de message valide, post_type_exists() et d’un type de message movie (ces deux vérifications sont excessives mais je l’ai fait pour vous montrer si vous ne le souhaitez pas. pour coder en dur le type de publication.) Enfin, j’utilise le paramètre URL sortby car il n’entre 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 hook parse_query appelé après que WordPress ait décidé quelle requête devrait être exécutée mais avant qu’elle ne soit exécutée. Ici, nous arrivons à définir les valeurs de orderby et meta_key dans le tableau query_var de la requête qui sont documentées dans Codex dans le paramètre orderby pour 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 l'administrateur ($pagenow=='edit.php'),
  3. La page a été appelée avec un paramètre d'URL post_type égal à movie, et
  4. La page a également été appelée avec un paramètre d'URL sortby et n'a pas été transmise avec la valeur 'Aucune'

Si tous ces tests réussissent, nous définissons le query_vars (comme documenté ici ) sur meta_value et notre valeur sortby 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. aucun crochet "posts_order" ou "wp" n'est 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 seront beaucoup plus confus. Donc, ajoutez un hook manage_{$post_type}_posts_columns, 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_columns avec une print_r() pour voir ce qui est disponible par défaut.)

J'ai décidé d'ajouter un "trié par:" lorsqu'il existe un paramètre d'URL sortby et qu'il n'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 crochet manage_pages_custom_column pour afficher la valeur quand il y a une publication du type de publication approprié et avec le test probablement redondant pour is_admin() et $pagenow=='edit.php'. Lorsqu'il existe un paramètre d'URL sortby, 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 commentaires de la galerie Peanut sur les classifications de films! :):

 Custom Columns added for a Custom Post Type in the WordPress Admin 
(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 une movie, c'est-à-dire la première méta_value dans le cas de plusieurs valeurs 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 probablement pour le novice dans le fichier functions.php de votre thème actuel.

Comment cela aide.

66
MikeSchinkel

Depuis WordPress 3.1 (j'utilise la version bêta), les colonnes peuvent maintenant être triées via leurs titres.

L'article suivant détaille comment les implémenter.

http://scribu.net/wordpress/custom-sortable-columns.html

8
Leo Plaw