Cum se sortează zona de administrare a unui tip de postare personalizat WordPress după un câmp personalizat
Când editez unul dintre tipurile mele de postări personalizate, vreau să pot lista toate intrările după un câmp personalizat în loc de data la care sunt publicate (care, pentru un tip de postare personalizat probabil nu este relevantă). Am primit un indiciu din comentariile unui articol de blog despre tipuri de postări personalizate și autorul a spus că este posibil și că a reușit chiar să facă posibilă sortarea făcând click pe numele coloanelor. El a menționat funcția posts_orderby
pe care am notat-o în propriile comentarii, dar acum nu mai pot găsi articolul de blog. Aveți sugestii? Am văzut o soluție care folosea
add_action('wp', 'check_page');
Iar funcția check_page
folosea add_filter
pentru a modifica interogarea, dar sunt destul de sigur că ar funcționa doar în fișierele temei, nu și în zona de administrare.

După cum probabil vă puteți imagina din lipsa răspunsurilor oferite, soluția nu este tocmai banală. Ceea ce am făcut este să creez un exemplu relativ autonom care presupune un tip de postare personalizată "movie
" și o cheie de câmp personalizat "Gen".
Notă: acest lucru funcționează cu WP3.0, dar nu pot fi sigur că va funcționa și cu versiunile anterioare.
În esență, aveți nevoie să conectați două (2) hook-uri pentru a face funcționalitatea să meargă și încă două (2) pentru a o face evidentă și utilă.
Primul hook este 'restrict_manage_posts
', care vă permite să afișați un HTML <select>
în zona de deasupra listei de postări unde se află filtrele "Acțiuni în masă" și "Afișează datele". Codul furnizat va genera funcționalitatea "Sortare după:" așa cum se vede în această captură de ecran:
(sursa: mikeschinkel.com)
Codul folosește SQL direct deoarece nu există o funcție API în WordPress care să ofere lista tuturor meta_keys pentru un tip de postare (sună a un potențial tichet trac în viitor...) Oricum, iată codul. Rețineți că preia tipul de postare din $_GET
și validează pentru a se asigura că este atât un tip de postare valid post_type_exists()
, cât și un tip de postare movie
(aceste două verificări sunt exagerate, dar le-am făcut pentru a vă arăta cum puteți proceda dacă nu doriți să hardcodați tipul de postare.) În final, folosesc parametrul URL sortby
deoarece nu intră în conflict cu nimic altceva în 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\">Fără sortare</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 "Sortare după: " . implode("\n",$html);
}
}
}
A doua etapă necesară este să folosim hook-ul parse_query
care este apelat după ce WordPress decide ce interogare ar trebui să ruleze, dar înainte de a rula interogarea. Aici avem ocazia să setăm valorile orderby
și meta_key
în tabloul query_var
al interogării, care sunt documentate în Codex în parametrul orderby
pentru query_posts()
. Testăm pentru a ne asigura că:
- Suntem în admin (
is_admin()
), - Suntem pe pagina care listează postările în admin (
$pagenow=='edit.php'
), - Pagina a fost apelată cu un parametru URL
post_type
egal cumovie
, și - Pagina a fost apelată și cu un parametru URL
sortby
și că acesta nu a primit valoarea 'None'
Dacă toate aceste teste sunt trecute, atunci setăm query_vars
(așa cum este documentat aici) la meta_value
și valoarea noastră sortby
pentru 'Gen':
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'];
}
}
Și asta este tot ce trebuie să faceți; nu sunt necesare hook-uri "posts_order
" sau "wp
"! Desigur, de fapt aveți nevoie să faceți mai mult; trebuie să adăugați câteva coloane pe pagina care listează postările pentru a putea vedea efectiv valorile după care se face sortarea, altfel utilizatorii vor fi foarte confuzi. Așadar, adăugați un hook manage_{$post_type}_posts_columns
, în acest caz manage_movie_posts_columns
. Acest hook primește tabloul implicit de coloane și, pentru simplitate, l-am înlocuit cu două coloane standard; o casetă de selectare (cb
) și un nume de postare (title
). (Puteți inspecta posts_columns
cu un print_r()
pentru a vedea ce altceva este disponibil implicit.)
Am decis să adaug un "Sortat după:" pentru când există un parametru URL sortby
și când acesta nu este 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' => 'Nume Film',
);
if (isset($_GET['sortby']) && $_GET['sortby'] !='None')
$posts_columns['meta_value'] = 'Sortat după';
return $posts_columns;
}
În final, folosim hook-ul manage_pages_custom_column
pentru a afișa efectiv valoarea atunci când există o postare de tipul corespunzător și cu testul probabil redundant pentru is_admin()
și $pagenow=='edit.php'
. Când există un parametru URL sortby
, extragem valoarea câmpului personalizat după care se face sortarea și o afișăm în lista noastră. Iată cum arată (rețineți, acestea sunt date de test, așa că nu comentați despre clasificările filmelor! :):
(sursa: mikeschinkel.com)
Și iată codul:
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;
}
}
}
Rețineți că acest lucru preia doar primul "Gen" pentru un movie
, adică prima meta_value în cazul mai multor valori pentru o cheie dată. Dar, din nou, nu sunt sigur cum ar funcționa altfel!
Și pentru cei care nu sunt familiarizați cu locul unde să puneți acest cod, îl puteți pune într-un plugin sau, mai probabil pentru începători, în fișierul functions.php
din tema curentă.
Sper că acest lucru vă ajută.

+1, doar pentru efort. Dar ar fi și mai bine dacă cercurile ar fi desenate manual :-)

Ai vreo idee cum să elimini complet filtrul SHOW ALL DATES, astfel încât să apară doar filtrele mele personalizate pentru un anumit tip de postare?

@RailsTweeter Folosește tehnica pe care am arătat-o aici, unde cele două hook-uri care încadrează generarea HTML sunt 'months_dropdown_results'
și 'restrict_manage_posts'
.
PS. Upvote-urile sunt întotdeauna apreciate. :)

@MikeSchinkel , acum că există un API pentru WordPress, acest lucru îți va actualiza cumva codul?

Începând cu WordPress 3.1 (eu folosesc versiunea beta), coloanele pot fi acum sortate prin intermediul titlurilor lor.
Următorul articol detaliază cum să le implementezi.

Iată o soluție simplă:
/* --------Evenimente Sortabile în Panou de Control - afișează data de început, ora, locația--------- */
/*-------------------------------------------------------------------------------
Coloane Personalizate
-------------------------------------------------------------------------------*/
function my_*YOUR POST TYPE*_columns($columns)
{
$columns = array(
'cb' => '<input type="checkbox" />',
'title' => 'Titlu',
'your_custom_field' => 'Nume Câmp Personalizat',
'date' => 'Dată',
);
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");
/*-------------------------------------------------------------------------------
Coloane Sortabile
-------------------------------------------------------------------------------*/
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" );
Doar înlocuiți YOUR POST TYPE și 'your_custom_field'
