Problem
WP wydaje się usuwać wartość mojej zmiennej zapytania, zanim zostanie ona użyta do filtrowania listy użytkowników.
Mój kod
Ta funkcja dodaje niestandardową kolumnę do mojej tabeli Użytkownicy na /wp-admin/users.php
:
function add_course_section_to_user_meta( $columns ) {
$columns['course_section'] = 'Section';
return $columns;
}
add_filter( 'manage_users_columns', 'add_course_section_to_user_meta' );
Ta funkcja mówi WP, jak wypełnić wartości w kolumnie:
function manage_users_course_section( $val, $col, $uid ) {
if ( 'course_section' === $col )
return get_the_author_meta( 'course_section', $uid );
}
add_filter( 'manage_users_custom_column', 'manage_users_course_section' );
To dodaje menu i Filter
przycisk nad tabelą Użytkownicy:
function add_course_section_filter() {
echo '<select name="course_section" style="float:none;">';
echo '<option value="">Course Section...</option>';
for ( $i = 1; $i <= 3; ++$i ) {
if ( $i == $_GET[ 'course_section' ] ) {
echo '<option value="'.$i.'" selected="selected">Section '.$i.'</option>';
} else {
echo '<option value="'.$i.'">Section '.$i.'</option>';
}
}
echo '<input id="post-query-submit" type="submit" class="button" value="Filter" name="">';
}
add_action( 'restrict_manage_users', 'add_course_section_filter' );
Ta funkcja zmienia zapytanie użytkownika, aby dodać moje meta_query
:
function filter_users_by_course_section( $query ) {
global $pagenow;
if ( is_admin() &&
'users.php' == $pagenow &&
isset( $_GET[ 'course_section' ] ) &&
!empty( $_GET[ 'course_section' ] )
) {
$section = $_GET[ 'course_section' ];
$meta_query = array(
array(
'key' => 'course_section',
'value' => $section
)
);
$query->set( 'meta_key', 'course_section' );
$query->set( 'meta_query', $meta_query );
}
}
add_filter( 'pre_get_users', 'filter_users_by_course_section' );
Inne informacje
Poprawnie tworzy moje menu rozwijane. Kiedy wybieram sekcję kursu i klikam, Filter
strona odświeża się i course_section
pojawia w adresie URL, ale nie ma z nią żadnej wartości. Jeśli sprawdzę żądania HTTP, pokaże, że jest przesyłane z poprawną wartością zmiennej, ale wtedy jest taka, 302 Redirect
która wydaje się usuwać wybraną wartość.
Jeśli prześlę course_section
zmienną, wpisując ją bezpośrednio w adresie URL, filtr działa zgodnie z oczekiwaniami.
Mój kod jest z grubsza oparty na tym kodzie z Dave Court .
Próbowałem również dodać białą listę do mojego zapytania var przy użyciu tego kodu, ale bez powodzenia:
function add_course_section_query_var( $qvars ) {
$qvars[] = 'course_section';
return $qvars;
}
add_filter( 'query_vars', 'add_course_section_query_var' );
Używam WP 4.4. Wszelkie pomysły, dlaczego mój filtr nie działa?
Odpowiedzi:
AKTUALIZACJA 28.06.2018
Chociaż poniższy kod w większości działa dobrze, oto przepisanie kodu dla WP> = 4.6.0 (przy użyciu PHP 7):
Włączyłem kilka pomysłów od @birgire i @cale_b, które oferują również rozwiązania, które warto przeczytać. W szczególności:
$which
zmiennej, która została dodanav4.6.0
__( 'Filter' )
array_map()
,array_filter()
Orazrange()
sprintf()
do generowania szablonów znacznikówarray()
Wreszcie odkryłem błąd w moich wcześniejszych rozwiązaniach. Te rozwiązania zawsze faworyzują TOP
<select>
nad DOLNYM<select>
. Jeśli więc wybierzesz opcję filtrowania z górnego menu rozwijanego, a następnie wybierz jeden z dolnego menu rozwijanego, filtr będzie nadal używał tylko tej wartości, która była na górze (jeśli nie jest pusta). Ta nowa wersja naprawia ten błąd.AKTUALIZACJA 14.02.2018
Ten problem został załatany od wersji WP 4.6.0, a zmiany są udokumentowane w oficjalnych dokumentach . Poniższe rozwiązanie nadal jednak działa.
Co było przyczyną problemu (WP <4.6.0)
Problem polegał na tym, że
restrict_manage_users
akcja jest wywoływana dwukrotnie: raz POWYŻEJ tabeli użytkowników i raz PONIŻEJ. Oznacza to, żeselect
tworzone są DWIE listy rozwijane o tej samej nazwie . PoFilter
kliknięciu przycisku dowolna wartość znajdująca się w drugimselect
elemencie (tj. PONIŻEJ tabeli) zastępuje wartość w pierwszym elemencie, tj. Powyżej tabeli.Jeśli chcesz zanurzyć się w źródle WP,
restrict_manage_users
akcja jest uruchamiana od wewnątrzWP_Users_List_Table::extra_tablenav($which)
, czyli funkcji, która tworzy natywne menu rozwijane, aby zmienić rolę użytkownika. Ta funkcja ma$which
zmienną, która mówi jej, czy tworzyselect
powyższą czy pod formularzem, i pozwala nadać obu listom różnename
atrybuty. Niestety$which
zmienna nie jest przekazywana dorestrict_manage_users
akcji, dlatego musimy wymyślić inny sposób na odróżnienie własnych elementów niestandardowych.Jednym ze sposobów na zrobienie tego, jak sugeruje @Linnea , byłoby dodanie JavaScript, aby go złapać
Filter
kliknięcie i zsynchronizować wartości dwóch list rozwijanych. Wybrałem rozwiązanie oparte tylko na PHP, które opiszę teraz.Jak to naprawić
Możesz skorzystać z możliwości przekształcania danych HTML w tablice wartości, a następnie filtrować tablicę, aby pozbyć się wszelkich niezdefiniowanych wartości. Oto kod:
Premia: Refaktor PHP 7
Ponieważ jestem podekscytowany PHP 7, na wypadek, gdybyś uruchomił WP na serwerze PHP 7, oto krótsza, bardziej seksowna wersja z operatorem koalescencji null
??
:Cieszyć się!
źródło
</select>
również i znalazłem, aby go uruchomić, musiałem umieścić<form method="get">
przed menu wyboru i</form>
po przycisku filtra.</select>
tagi! Dodałem je. Dziwne, że musiałeś to zawinąć,<form>
ponieważ cała strona jest owinięta w jedną dużą formę, a ten kod zostaje wstrzyknięty w jej środek. Cieszę się, że to działa. :)W rdzeniu dolne nazwy wejściowe są oznaczone numerem instancji, np.
new_role
(Góra) inew_role2
(dół). Oto dwa podejścia do podobnej konwencji nazewnictwa, a mianowiciecourse_section1
(u góry) icourse_section2
(u dołu):Podejście nr 1
Ponieważ
$which
zmienna ( góra , dół ) nie jest przekazywana dorestrict_manage_users
haka, możemy to obejść, tworząc własną wersję tego haka:Utwórzmy hak akcji,
wpse_restrict_manage_users
który ma dostęp do$which
zmiennej:Następnie możemy zaczepić o:
gdzie mamy teraz
$name
jakcourse_section1
na górze icourse_section2
na dole .Podejście nr 2
Zahaczmy się
restrict_manage_users
, aby wyświetlić menu rozwijane, z inną nazwą dla każdej instancji:gdzie użyliśmy funkcji podstawowej
selected()
i funkcji pomocniczej:Następnie moglibyśmy tego użyć, gdy sprawdzimy wybraną sekcję kursu w
pre_get_users
wywołaniu zwrotnym akcji.źródło
static
słowa kluczowego w ten sposób (tylko w ramach klas). Czy$instance
kiedy to zrobisz, stanie się zmienną globalną? Czy musisz się martwić kolizjami nazw zmiennych? Podoba mi się również technika tworzenia nowej akcji, która opiera się na istniejącej. Dzięki!Przetestowałem twój kod zarówno w Wordpress 4.4, jak i Wordpress 4.3.1. W wersji 4.4 napotykam dokładnie ten sam problem, co ty. Jednak Twój kod działa poprawnie w wersji 4.3.1!
Myślę, że to błąd Wordpress. Nie wiem, czy zostało to jeszcze zgłoszone. Myślę, że przyczyną błędu może być to, że przycisk wysyłania przesyła zmienne zapytania dwukrotnie. Jeśli spojrzysz na zmienne zapytania, zobaczysz, że sekcja_kursu jest wymieniona dwa razy, raz z poprawną wartością, a raz pusta.
Edycja: To jest rozwiązanie JavaScript
Po prostu dodaj to do pliku functions.php swojego motywu i zmień NAME_OF_YOUR_INPUT_FIELD na nazwę swojego pola wejściowego! Ponieważ WordPress automatycznie ładuje jQuery po stronie administratora, nie musisz kolejkować żadnych skryptów. Ten fragment kodu po prostu dodaje detektor zmian do danych rozwijanych, a następnie automatycznie aktualizuje inne menu rozwijane, aby dopasować tę samą wartość. Więcej wyjaśnień tutaj.
Mam nadzieję że to pomoże!
źródło
Filter
przesyła poprawną wartość, ale następnie przekierowuje z powrotem na stronę, tym razem usuwając wartość. Domyślam się, że jest to pewnego rodzaju „funkcja” bezpieczeństwa, która zapobiega przesyłaniu losowych, potencjalnie złośliwych wartości, ale nie wiem, jak sobie z tym poradzić. Westchnienie.name
atrybut. Jeśli użyję menu rozwijanego PONIŻEJ tabeli, aby wykonać filtrowanie, działa ono zgodnie z oczekiwaniami. Ponieważ to pole występuje po polu powyżej, jego wartość zerowa zastępuje wcześniejsze. Hmmm ....To jest inne rozwiązanie JavaScript, które może być pomocne dla niektórych osób. W moim przypadku po prostu całkowicie usunąłem 2. (dolną) listę wyboru. Uważam, że i tak nigdy nie używam dolnych danych wejściowych ...
źródło
Rozwiązanie inne niż JavaScript
Nadaj wyborowi nazwę „w stylu tablicowym”, taką jak:
Następnie przekazywane są parametry OBA (od góry i dołu tabeli), a teraz w znanym formacie tablicowym.
Następnie można użyć tej wartości w
pre_get_users
funkcji:źródło
inne rozwiązanie
możesz umieścić pole wyboru filtra w osobnym pliku, np
user_list_filter.php
i użyj
require_once 'user_list_filter.php'
w swojej funkcji wywołania zwrotnego akcjiuser_list_filter.php
plik:i w twoim działaniu zwrotnym:
źródło