Jak najlepiej obsługiwać niestandardowe działania strony wtyczki?

21

Ciągle mam taką samą irytację, więc pomyślałem, że zobaczę, czy są jakieś pomysły lub doświadczenia ...

Utworzyłem wtyczkę, która korzysta z własnej strony administratora. Musi. Teraz, gdy uporządkowałem rzeczy WP_List_Table (), muszę powiedzieć, że jest świetny ... ale ...

Niestandardowe strony wtyczek są zawsze ładowane, admin.php?page=...chyba że chcę je załadować bezpośrednio z katalogu wtyczek, czego nie robię. Teraz, jeśli wykonam „akcję” z tej strony, muszę ją jakoś przetworzyć, a następnie przekierować z powrotem na stronę bez parametru akcji. Bez względu na to, czy robię GET, czy POST, naprawdę.

Na wszystkich swoich wewnętrznych stronach WP robi to na tej samej stronie, sprawdza, czy jest jakieś działanie, jeśli je przetwarza, a następnie przekierowuje do siebie bez działania. Jest to możliwe, ponieważ na tych stronach admin-headerjeszcze nie został załadowany.

Jeśli jednak spróbujesz to zrobić na własnej stronie, połowa interfejsu administratora została już wysłana do przeglądarki, więc przekierowanie nie jest już możliwe. Najwyraźniej rozwiązaniem jest POST / GET bezpośrednio na inną stronę, załadowanie do niej frameworka WP, wykonanie przetwarzania, a następnie przekierowanie z powrotem do oryginalnej strony ... ale ... to trochę denerwujące, ponieważ ... moja oryginalna strona jest ładowana przez wywołanie zwrotne, więc działa w ramach metody mojej klasy. To jest piękne.

Jeśli załaduję osobną stronę, muszę ręcznie dołączyć wp-load.phpi być poza moją klasą, co jest denerwujące, aw moim przypadku szczególnie mnie wkurza, ponieważ instynktownie instynktuję moją klasę wtyczek, aby nikt nie miał do niej dostępu z zewnątrz.

Więc po tej długiej historii ... czy ktoś wymyślił dobre rozwiązanie, aby załadować kolejną stronę za pomocą wywołania zwrotnego, bez konfigurowania całego interfejsu administratora?

(Wiem o obejściu ... mogę podłączyć funkcję, load-....która sprawdza parametr akcji oraz wykonuje przetwarzanie i przekierowuje. Ale zastanawiam się, czy jest lepszy sposób.)

Dzięki.

wyrfel
źródło
Dlaczego jest to oznaczone [plugin-wp-pagenavi]? [plugin-development]z pewnością jest tu mile widziany.
Jan Fabry
@Jan Fabry: Nie jestem pewien, po co plugin-wp-pagenavi... założyłem, że dotyczy to korelacji między wtyczkami a menu administratora. Ponieważ moje pytanie jest z tym związane, wybrałem ten tag.
wyrfel
WP-PageNavi to wtyczka z bardziej zaawansowaną nawigacją stronicowania dla interfejsu użytkownika. Możesz użyć [admin-menu]tutaj, ale nie sądzę, żeby to było naprawdę związane z tym. Zmieniłem tagi na to, co moim zdaniem pasuje, możesz oczywiście ponownie je edytować.
Jan Fabry
@Jan Fabry: Dzięki za ponowne tagowanie ... jeszcze nie zaznajomiony z całą pulą znaczników, ale (oczywiście).
wyrfel

Odpowiedzi:

28

Zasadniczo należy stosować żądanie POST dla większości działań, aby upewnić się, że nie zostaną one wykonane przypadkowo . Ale dobrą praktyką jest również przekierowanie na normalną stronę po żądaniu POST, aby zapobiec duplikowaniu wykonania, gdy użytkownik odświeży stronę.

Więc przepływ jest taki:

  1. Twoja strona wtyczki z formularzem POST, który przesyła się na
  2. Strona obsługująca żądanie, które przekierowuje do
  3. Twoja strona wtyczki, która pokazuje wynik działania

Środkowa strona nie musi być stroną wtyczki. Oznacza to, że można korzystać z „rodzajowe obsługi POST” , który został dołączony trzy lata temu, z 'admin_action_' . $_REQUEST['action']hakiem wadmin.php .

Przykładowym użytkownikiem jest wtyczka Akismet . Jeśli chcesz go używać niezawodnie, musisz przesłać go admin.phpbezpośrednio , a nie na inną stronę, która się na nim znajduje admin.php.

Oto bardzo prosty przykład tego, jak z niego korzystać:

add_action( 'admin_action_wpse10500', 'wpse10500_admin_action' );
function wpse10500_admin_action()
{
    // Do your stuff here

    wp_redirect( $_SERVER['HTTP_REFERER'] );
    exit();
}

add_action( 'admin_menu', 'wpse10500_admin_menu' );
function wpse10500_admin_menu()
{
    add_management_page( 'WPSE 10500 Test page', 'WPSE 10500 Test page', 'administrator', 'wpse10500', 'wpse10500_do_page' );
}

function wpse10500_do_page()
{
?>
<form method="POST" action="<?php echo admin_url( 'admin.php' ); ?>">
    <input type="hidden" name="action" value="wpse10500" />
    <input type="submit" value="Do it!" />
</form>
<?php
}
Jan Fabry
źródło
Hej, jeszcze raz popatrzę na kod, oczywiście tego nie widziałem, ale tylko po to, aby potwierdzić ... więc mówisz, że jeśli wywołam admin.php bezpośrednio bez parametru strony, pominie całą stronę ładowanie i po prostu inicjuje i uruchamia hak? To byłoby niesamowite ... ish (wciąż nie rozumiem, dlaczego nie założyli haka przed załadowaniem strony).
wyrfel
@wyrfel: Tak, admin.phpbezpośrednie dzwonienie to „sztuczka”, której nauczyło mnie źródło Akismet. Masz rację, gdy wyświetlasz formularz i chcesz wyświetlić go ponownie w przypadku błędów: wtedy byłoby łatwo, gdyby miejscem docelowym była strona wtyczki, ale zaczepienie gdzieś na początku (abyś mógł przekierować, jeśli się powiedzie, lub wyświetlić formularz ponownie z komunikatami o błędach, jeśli nie). Może zasugerujesz to na bilecie Trac?
Jan Fabry
Złożę bilet. W celu obejścia tego problemu znalazłem 'load-<pagehook>'hak do działania ... jest on wywoływany przed załadowaniem strony ... ale admin_action_...koncepcja wydaje się o wiele ładniejsza i bardziej szczegółowa. Uwaga: komunikaty o błędach są nadal problematyczne, jeśli wykonujesz testy POST i nie chcesz ponownie ładować przy przeładowaniu, ale to inny temat.
wyrfel
@wyrfel: Dlaczego komunikaty o błędach nadal stanowią problem? Jeśli pojawi się komunikat o błędzie, pozostań na stronie i ponownie wyświetl formularz wraz z komunikatami (oczywiście odświeżenie nie ma tutaj większego sensu - ale również nie zaszkodzi, ponieważ błędy nadal będą występować i nie będzie żadnych działań być straconym). Jeśli nie ma błędów, wykonaj akcję i przekieruj na „bezpieczną” stronę przeglądu. To by działało - gdyby admin_action_hak został przesunięty przed modułem ładującym strony wtyczki.
Jan Fabry
Ok ... myślałem zbyt skomplikowany.
wyrfel
3

Podszedłem do tego nieco inaczej, po prostu dodając noheader = true do adresu URL akcji na stronie, na której użytkownik przesyła akcję.

Mój program obsługi następnie wykonuje akcję (tj. Zazwyczaj dodaje, aktualizuje lub usuwa), a następnie kończy działanie wp_redirect () do następnej akcji strony (np. Dodaj stronę -> edytuj stronę, usuń stronę -> stronę listy, edytuj stronę -> edytuj stronę ). Przekazuję również wiadomość na adres URL, dzięki czemu mogę wyświetlić stan, np. Aktualizację zakończoną powodzeniem lub niepowodzeniem.

Dzięki takiemu podejściu wszystkie działania: lista, dodawanie, edycja, usuwanie, usuwanie zbiorcze itp. Znajdują się w tej samej klasie i przy użyciu tego samego narzędzia administratora, dzięki czemu jest dość łatwe w utrzymaniu i zrozumieniu.

Russell Jamieson
źródło
Człowieku, jesteś genialny! Walczę od dwóch dni z rzędu i wydaje się, że wszystko, czego potrzebowałem, to część „noheader = true”. Dzięki!
r00m
0

Innym innym podejściem jest po prostu dodanie ukrytego pola wejściowego do formularza:

<input type="hidden" name="page" value="your-page-slug" />

W ten sposób WordPress wydaje się automatycznie obsługiwać przekierowanie.

simonthesorcerer
źródło