Como classificar a área administrativa de um tipo de postagem personalizada do WordPress por um campo personalizado

52

Ao editar um dos meus tipos de postagem personalizados, desejo listar todas as entradas por um campo personalizado, em vez da data em que são publicadas (o que, para um tipo de postagem personalizado, provavelmente não é relevante). Eu recebi uma vantagem dos comentários de uma postagem de blog sobre tipos de postagem personalizados e o autor disse que era possível e que ele chegou até você para que você pudesse clicar nos nomes das colunas para obter uma classificação personalizada. Ele mencionou a posts_orderbyfunção que observei em meus próprios comentários, mas agora posso encontrar mais o post do blog. Alguma sugestão? Eu vi uma solução que usava

add_action('wp', 'check_page');

E a check_pagefunção usada add_filterpara alterar a consulta, mas tenho certeza de que funcionaria apenas nos arquivos de tema, não na área de administração.

tooshel
fonte
11
Aqui está outra resposta útil, para classificar as postagens por .... <br/> wordpress.stackexchange.com/questions/66455/…
T.Todua

Respostas:

66

Como você provavelmente pode imaginar pela falta de respostas fornecidas, a solução não é exatamente trivial. O que eu fiz foi criar um exemplo um pouco independente que pressupõe um tipo de postagem personalizado de " movie" e uma chave de campo personalizada de " Gênero ".

Isenção de responsabilidade : isso funciona com o WP3.0, mas não tenho certeza se ele funcionará com versões anteriores.

Você basicamente precisa conectar dois (2) ganchos para fazê-lo funcionar e outros dois (2) para torná-lo óbvio e útil.

O primeiro gancho é ' restrict_manage_posts', que permite emitir um HTML <select>na área acima da lista de postagens em que os filtros " Ações em massa " e " Mostrar datas ". O código fornecido gerará a funcionalidade " Classificar por: ", como visto neste snippet da tela:

Como criar a funcionalidade Classificar por para um tipo de postagem personalizado no WordPress Admin
(fonte: mikeschinkel.com )

O código usa o SQL direto porque não há uma função da API do WordPress para fornecer a lista de todas as meta_keys para tipos de postagens (parece um ticket trac futuro para mim ...) De qualquer forma, aqui está o código. Observe que ele pega o tipo de postagem $_GETe valida para garantir que seja um tipo de postagem válido post_type_exists()e também um movietipo de postagem (essas duas verificações são um exagero, mas eu fiz isso para mostrar a você como se você não quiser codifique o tipo de postagem.) Por fim, uso o sortbyparâmetro URL, pois não entra em conflito com mais nada no 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);
        }
    }
}

A segunda etapa necessária é usar o parse_querygancho chamado depois que o WordPress decidir um que consulta deve ser executada, mas antes de executá-la. Aqui, podemos definir valores de orderbye meta_keyna query_varmatriz da consulta que estão documentados no Codex no orderbyparâmetro for query_posts(). Testamos para garantir que:

  1. Estamos no admin ( is_admin()),
  2. Estamos na página que lista as postagens no admin ( $pagenow=='edit.php'),
  3. A página foi chamada com um post_typeparâmetro de URL igual a movie, e
  4. A página também foi chamada com um sortbyparâmetro de URL e não recebeu um valor de ' Nenhum '

Se todos esses testes forem aprovados, definiremos o query_vars(como documentado aqui ) como meta_valuee nosso sortbyvalor para ' Gênero ':

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'];
    }
}

E é tudo o que você precisa fazer; não são necessários ganchos " posts_order" ou " wp"! Claro que você realmente precisa fazer mais; você precisa adicionar algumas colunas em sua página que listam as postagens, para que você possa realmente ver os valores pelos quais está classificando, caso contrário os usuários ficarão confusos. Portanto, adicione um manage_{$post_type}_posts_columnsgancho, neste caso manage_movie_posts_columns. Esse gancho é passado na matriz padrão de colunas e, por simplicidade, substituí-o por duas colunas padrão; uma caixa de seleção ( cb) e um nome de postagem ( title). (Você pode inspecionar posts_columnscom a print_r()para ver o que mais está disponível por padrão.)

Decidi adicionar um " Ordenado por: " para quando houver um sortbyparâmetro de URL e quando não houver 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;
}

Finalmente, usamos o manage_pages_custom_columngancho para realmente exibir o valor quando há uma postagem do tipo de postagem apropriada e com o teste provavelmente redundante para is_admin()e $pagenow=='edit.php'. Quando existe um sortbyparâmetro de URL, extraímos o valor do campo personalizado que está sendo classificado por um exibi-lo em nossa lista. Aqui está o que parece (lembre-se, são dados de teste, portanto, não há comentários da galeria de amendoins nas classificações de filmes! :):

Colunas personalizadas adicionadas para um Tipo de postagem personalizado no WordPress Admin
(fonte: mikeschinkel.com )

E aqui está o código:

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;
        }
    }
}

Observe que isso seleciona apenas o primeiro " Gênero " para a movie, ou seja, o primeiro meta_value no caso de vários valores para uma determinada chave. Mas, novamente, não tenho certeza de como isso funcionaria de outra maneira!

E para aqueles que não estão familiarizados com onde colocar esse código, você pode colocá-lo em um plug-in ou, mais provavelmente, para o iniciante no functions.phparquivo em seu tema atual.

Como isso ajuda.

MikeSchinkel
fonte
2
+1, apenas pelo esforço. Mas seria ainda melhor se os círculos foram desenhados à mão :-)
Jan Fabry
Alguma idéia de como remover completamente o filtro SHOW ALL DATES para que apenas meus filtros personalizados sejam exibidos para um determinado tipo de postagem?
RailsTweeter
@RailsTweeter Use a técnica eu mostrei aqui, onde os dois ganchos que encerrem a geração HTML são 'months_dropdown_results'e 'restrict_manage_posts'. Upvotes PS são sempre apreciados. :)
MikeSchinkel
@ MikeSchinkel, agora que existe uma API WP, isso atualizará um pouco o seu código?
samjco 16/02
@samjco Não tenho certeza. Infelizmente, não tenho tempo para revisar isso no momento.
MikeSchinkel 17/02
-1

Aqui está uma solução simples:

/* --------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" );

Apenas substitua SEU POST TYPE e 'your_custom_field'

Jake
fonte