Filtrare după câmp personalizat în tip de postare personalizat pe pagina de administrare
Am folosit Advanced Custom Fields pentru a crea câmpuri personalizate pentru numele competiției, răspunsuri etc. Am creat un tip de postare personalizat pentru competiții așa cum se arată în imagine și am folosit functions.php din WordPress pentru a crea coloanele din valorile câmpurilor mele personalizate.
Încerc să obțin o casetă dropdown "Filtrează după" cu diferitele nume/etichete ale competițiilor așa cum se arată mai jos, dar pot găsi doar soluții folosind taxonomii, pe care prefer să nu le folosesc dacă este posibil deoarece am folosit doar câmpuri personalizate pentru tot restul.
Este posibil să creez un dropdown "Filtrează după" personalizat folosind doar câmpuri personalizate?
Și pentru afișarea rezultatului pentru Filtru, încercați acest cod
add_filter( 'parse_query', 'prefix_parse_filter' );
function prefix_parse_filter($query) {
global $pagenow;
$current_page = isset( $_GET['post_type'] ) ? $_GET['post_type'] : '';
if ( is_admin() &&
'competition' == $current_page &&
'edit.php' == $pagenow &&
isset( $_GET['competition-name'] ) &&
$_GET['competition-name'] != '' ) {
$competition_name = $_GET['competition-name'];
$query->query_vars['meta_key'] = 'competition_name';
$query->query_vars['meta_value'] = $competition_name;
$query->query_vars['meta_compare'] = '=';
}
}
Schimbați meta_key și meta_value după cum este necesar. Am folosit "competition name" ca meta_key și "competition-name" ca nume pentru meniul drop-down select.

Acțiunea restrict_manage_posts declanșează funcția add_extra_tablenav()
, care este modalitatea prin care adăugați dropdown-uri suplimentare la tabela dorită.
În exemplul de mai jos, verificăm mai întâi dacă Post Type este corect, apoi extragem toate valorile din baza de date stocate pentru cheia competition_name
din tabela postmeta
(trebuie să schimbați numele cheii conform necesităților). Interogarea este destul de simplă și verifică doar dacă Competiția este publicată, ia doar valori unice (nu doriți duplicări în dropdown) și le ordonează alfabetic.
Apoi verificăm dacă există rezultate (nu are sens să afișăm dropdown-ul fără niciun rezultat), și construim opțiunile (inclusiv una implicită pentru afișarea tuturor). În final, dropdown-ul este afișat.
După cum am menționat în comentariul meu, aceasta nu este tot; veți avea nevoie de o logică suplimentară pentru a spune tabelului să afișeze doar rezultatele dorite atunci când filtrul este activ, dar vă las să vă uitați la asta și să începeți o altă întrebare dacă aveți nevoie de ajutor suplimentar. Sugestie - verificați fișierul /wp-admin/includes/class-wp-posts-list-table.php
și părintele său .../wp-class-list-table.php
/**
* Adaugă dropdown-uri suplimentare la tabelele de listare
*
* @param required string $post_type Tipul de postare afișat
*/
add_action('restrict_manage_posts', 'add_extra_tablenav');
function add_extra_tablenav($post_type){
global $wpdb;
/** Asigură-te că acesta este tipul corect de postare */
if($post_type !== 'competition')
return;
/** Extrage rezultatele din baza de date */
$query = $wpdb->prepare('
SELECT DISTINCT pm.meta_value FROM %1$s pm
LEFT JOIN %2$s p ON p.ID = pm.post_id
WHERE pm.meta_key = "%3$s"
AND p.post_status = "%4$s"
AND p.post_type = "%5$s"
ORDER BY "%6$s"',
$wpdb->postmeta,
$wpdb->posts,
'competition_name', // Cheia meta - schimbați conform necesităților
'publish', // Starea postării - schimbați conform necesităților
$post_type,
'competition_name'
);
$results = $wpdb->get_col($query);
/** Verifică dacă există opțiuni de afișat */
if(empty($results))
return;
// obține opțiunea selectată dacă există una
if (isset( $_GET['competition-name'] ) && $_GET['competition-name'] != '') {
$selectedName = $_GET['competition-name'];
} else {
$selectedName = -1;
}
/** Pregătește toate opțiunile care trebuie afișate */
$options[] = sprintf('<option value="-1">%1$s</option>', __('Toate Competițiile', 'your-text-domain'));
foreach($results as $result) :
if ($result == $selectedName) {
$options[] = sprintf('<option value="%1$s" selected>%2$s</option>', esc_attr($result), $result);
} else {
$options[] = sprintf('<option value="%1$s">%2$s</option>', esc_attr($result), $result);
}
endforeach;
/** Afișează meniul dropdown */
echo '<select class="" id="competition-name" name="competition-name">';
echo join("\n", $options);
echo '</select>';
}

Când folosesc asta, primesc eroarea Notice: wpdb::prepare was called incorrectly. The query does not contain the correct number of placeholders (6) for the number of arguments passed (5). Please see Debugging in WordPress for more information. (This message was added in version 4.8.3.) in /[...]/wp-includes/functions.php on line 4773

Dacă acest lucru nu funcționează pentru cineva, soluția mea a fost să adaug coloana pe care încercam să o filtrez la lista de coloane sortabile pentru tipul meu de postare personalizat.
// Face coloanele personalizate ale tipului de postare să fie sortabile
function cpt_custom_columns_sortable( $columns ) {
// Adaugă coloanele noastre în array-ul $columns
$columns['item_number'] = 'item_number';
$columns['coat_school'] = 'coat_school';
return $columns;
} add_filter( 'manage_edit-your-custom-post-type-slug_sortable_columns', 'cpt_custom_columns_sortable' );

Înlocuiți interogarea de mai jos pentru a corecta eroarea wpdb:prepare:
$query = $wpdb->prepare('
SELECT DISTINCT pm.meta_value FROM %1$s pm
LEFT JOIN %2$s p ON p.ID = pm.post_id
WHERE pm.meta_key = "%3$s"
AND p.post_status = "%4$s"
AND p.post_type = "%5$s"
ORDER BY "%3$s"',
$wpdb->postmeta,
$wpdb->posts,
'competition_name', // Cheia meta - schimbați după necesitate
'publish', // Statusul postării - schimbați după necesitate
$post_type,
'competition_name' //necesar a doua oară pentru a defini "%3$s" în ORDER BY
);

Am întâmpinat aceeași problemă când încercam să filtrez un custom-post-type după un custom-field,
dar am rezolvat problema urmând următorii pași.
Am convertit numele custom-field din writer
în _writer
și apoi am actualizat următorul cod în interiorul funcției callback
a hook-ului parse_query
pentru a putea adăuga meta_query pentru custom-field astfel:
$query->set( 'meta_query', array(
array(
'key' => '_writer',
'compare' => '=',
'value' => $_GET['_writer'],
'type' => 'numeric',
)
) );
Această soluție de mai sus a funcționat pentru mine.
Documentație https://developer.wordpress.org/reference/hooks/pre_get_posts/
Link-uri utile https://developer.wordpress.org/reference/hooks/pre_get_posts/#comment-2571
https://stackoverflow.com/questions/47869905/how-can-i-filter-records-in-custom-post-type-list-in-admin-based-on-user-id-that
