Cum gestionez cel mai bine acțiunile paginilor pentru plugin-uri personalizate?

26 feb. 2011, 02:44:19
Vizualizări: 33.5K
Voturi: 26

Mă confrunt constant cu aceeași problemă enervantă, așa că m-am gândit să văd dacă există idei sau experiențe în acest sens...

Am creat un plugin care folosește propria sa pagină de administrare. Este necesar acest lucru. Acum că am rezolvat problemele cu WP_List_Table(), trebuie să spun că e grozav... dar...

Paginile personalizate ale plugin-ului se încarcă întotdeauna ca admin.php?page=... dacă nu vreau să le încarc direct din directorul plugin-ului, ceea ce nu doresc. Acum, dacă execut o 'acțiune' din acea pagină, trebuie să o procesez cumva și apoi să redirecționez înapoi la pagină fără parametrul de acțiune. Nu contează dacă folosesc GET sau POST.

Pe toate paginile sale interne, WordPress face acest lucru pe aceeași pagină, verifică dacă există o acțiune, dacă da, o procesează și apoi redirecționează către sine fără acțiune. Acest lucru este posibil deoarece pe aceste pagini admin-header nu a fost încă încărcat.

Dacă încerci să faci asta pe propria ta pagină, totuși, jumătate din interfața de administrare a fost deja trimisă către browser, așa că o redirecționare nu mai este posibilă. În mod clar, soluția este să trimiți POST/GET direct către o altă pagină, să încarci framework-ul WordPress pe aceasta, să faci procesarea și apoi să redirecționezi înapoi la pagina originală... dar... este puțin enervant, pentru că... pagina mea originală este încărcată printr-un callback, deci rulează în cadrul unei metode din clasa mea. Ceea ce e frumos.

Dacă încarc o pagină separată, trebuie să includ manual wp-load.php și sunt în afara clasei mele, ceea ce este enervant, și în cazul meu particular mă deranjează în special, pentru că instanțiez clasa plugin-ului meu doar anonim astfel încât nimeni să nu poată accesa din exterior.

Deci după această poveste lungă... a găsit cineva o soluție bună pentru a încărca o altă pagină printr-un callback fără a avea întreaga interfață de administrare deja configurată în jurul ei?

(Cunosc o soluție alternativă... pot să agăț o funcție în load-.... care verifică parametrul de acțiune și face procesarea și redirecționarea. Dar mă întreb dacă există o cale mai bună.)

Mulțumesc.

4
Comentarii

De ce este etichetat cu [plugin-wp-pagenavi]? [plugin-development] este cu siguranță binevenit aici.

Jan Fabry Jan Fabry
28 feb. 2011 23:10:04

@Jan Fabry: Nu sunt sigur pentru ce este plugin-wp-pagenavi... am presupus că este pentru aspecte legate de corelația dintre plugin-uri și meniul de administrare. Deoarece întrebarea mea este legată de acest subiect, am selectat acea etichetă.

wyrfel wyrfel
1 mar. 2011 00:11:43

WP-PageNavi este un plugin cu o navigare mai avansată de paginare pentru front-end. Ai putea folosi [admin-menu] aici, dar nu cred că este chiar legat de asta. Am schimbat etichetele în ceea ce cred că se potrivește, poți să le editezi din nou dacă dorești.

Jan Fabry Jan Fabry
1 mar. 2011 10:12:11

@Jan Fabry: Mulțumesc pentru reetichetare... nu sunt încă foarte familiarizat cu întregul set de etichete (destul de evident).

wyrfel wyrfel
1 mar. 2011 11:52:10
Toate răspunsurile la întrebare 3
7
32

Ca regulă generală, ar trebui să utilizați o cerere POST pentru majoritatea acțiunilor, pentru a vă asigura că acestea nu sunt executate accidental. De asemenea, este o bună practică să redirecționați către o pagină normală după o cerere POST, pentru a preveni executarea duplicată când utilizatorul reîmprospătează pagina.

Deci fluxul este următorul:

  1. Pagina dvs. de plugin cu un formular POST, care trimite către
  2. O pagină care procesează cererea, care redirecționează către
  3. Pagina dvs. de plugin, care afișează rezultatul acțiunii

Pagina intermediară nu trebuie să fie pagina dvs. de plugin. Aceasta înseamnă că puteți utiliza "manipulatorul generic POST" care a fost inclus acum trei ani, hook-ul 'admin_action_' . $_REQUEST['action'] din admin.php.

Un exemplu de utilizator este plugin-ul Akismet. Dacă doriți să îl utilizați în mod fiabil, trebuie să trimiteți direct către admin.php, nu către o altă pagină care include întâmplător admin.php.

Iată un exemplu foarte simplu de utilizare:

add_action( 'admin_action_wpse10500', 'wpse10500_admin_action' );
function wpse10500_admin_action()
{
    // Faceți ce aveți de făcut aici

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

add_action( 'admin_menu', 'wpse10500_admin_menu' );
function wpse10500_admin_menu()
{
    add_management_page( 'Pagina de test WPSE 10500', 'Pagina de test WPSE 10500', '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="Execută!" />
</form>
<?php
}
28 feb. 2011 23:08:50
Comentarii

Hei, voi analiza din nou codul, evident că nu am observat asta, dar doar pentru a confirma... deci ceea ce spui este că dacă apelez admin.php direct fără un parametru de pagină, sar peste încărcarea paginii și doar face o inițializare și rulează hook-ul? Asta ar fi minunat... oarecum (tot nu înțeleg de ce nu au pus hook-ul înainte de încărcarea paginii).

wyrfel wyrfel
1 mar. 2011 00:27:51

@wyrfel: Da, apelarea directă a admin.php este "trucul" pe care l-am învățat din sursa Akismet. Ai dreptate când afișezi un formular și vrei să-l afișezi din nou în caz de erori: atunci ar fi ușor dacă destinația este pagina ta de plugin, dar hook-ul undeva la început (astfel încât să poți redirecționa dacă e succes, sau să afișezi din nou formularul cu mesaje de eroare dacă nu). Poți sugera asta într-un ticket Trac?

Jan Fabry Jan Fabry
1 mar. 2011 10:14:22

Voi depune un ticket. Ca soluție temporară, am descoperit că hook-ul 'load-<pagehook>' funcționează... este apelat înainte de încărcarea paginii... dar conceptul admin_action_... pare mult mai elegant și mai specific. De asemenea, pe o notă, mesajele de eroare sunt încă problematice dacă faci POST-uri și nu vrei să retrimiți la reîncărcare, dar asta e alt subiect.

wyrfel wyrfel
1 mar. 2011 11:50:03

@wyrfel: De ce mesajele de eroare ar fi în continuare problematice? Dacă există un mesaj de eroare, rămâi pe pagină și afișează din nou formularul cu mesajele (desigur, o reîmprospătare nu ar avea prea mult sens aici - dar nici nu ar face rău, deoarece erorile ar fi în continuare acolo și nicio acțiune nu va fi executată). Dacă nu există erori, execută acțiunea și redirecționează către o pagină de prezentare generală "sigură". Aceasta ar funcționa - dacă cârligul admin_action_ ar fi mutat înaintea încărcătorului de pagini al pluginului.

Jan Fabry Jan Fabry
1 mar. 2011 12:23:12

Ok...mă gândeam prea complicat.

wyrfel wyrfel
1 mar. 2011 12:57:14

Am extins acest post și am activat aceleași metode 'admin-action' pentru a fi apelate din URL-uri 'post-row-action'. Soluția folosește Jquery pentru a mapa un URL GET la cererea POST FORM pe care o abordează acest răspuns. http://wordpress.stackexchange.com/questions/82761/how-can-i-link-post-row-actions-with-a-custom-action-function

emeraldjava emeraldjava
28 mar. 2014 19:13:31

Pentru a fi în siguranță, ar trebui să generați un nonce în formular folosind wp_nonce_field, și să verificați nonce-ul în handler-ul de acțiuni folosind wp_verify_nonce.

Flimm Flimm
2 sept. 2020 16:25:17
Arată celelalte 2 comentarii
1

Am abordat acest lucru ușor diferit prin simpla adăugare a parametrului noheader=true la URL-ul de acțiune de pe pagina unde utilizatorul trimite acțiunea.

Handler-ul meu apoi execută acțiunea (de exemplu, de obicei o adăugare, actualizare sau ștergere) și se încheie cu un wp_redirect() către următoarea pagină de acțiune (de ex. pagină de adăugare -> pagină de editare, pagină de ștergere -> pagină de listare, pagină de editare -> pagină de editare). De asemenea, transmit un mesaj în URL pentru a putea afișa un status precum actualizare reușită sau eșuată.

Această abordare păstrează toate acțiunile: listare, adăugare, editare, ștergere, ștergere în masă etc. în aceeași clasă și cu același slug de admin, astfel încât este destul de ușor de întreținut și de înțeles.

29 aug. 2011 15:22:57
Comentarii

Omule, ești geniu! M-am chinuit două zile la rând și se pare că tot ce aveam nevoie era partea cu "noheader=true". Mulțumesc!

roman roman
9 apr. 2014 13:37:43
0

O altă abordare diferită este simpla adăugare a unui câmp de input ascuns în formular:

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

În acest fel, WordPress pare să gestioneze redirecționarea automat.

16 ian. 2015 18:02:23