Come gestire al meglio le azioni delle pagine dei plugin personalizzati?

26 feb 2011, 02:44:19
Visualizzazioni: 33.5K
Voti: 26

Mi imbatto costantemente nello stesso fastidio, quindi ho pensato di vedere se ci sono idee o esperienze a riguardo...

Ho creato un plugin che utilizza la sua pagina di amministrazione. È necessario. Ora che ho sistemato la questione di WP_List_Table(), devo dire che è fantastico... ma...

Le pagine dei plugin personalizzati vengono sempre caricate come admin.php?page=... a meno che non voglia caricarle direttamente dalla directory del plugin, cosa che non voglio. Ora, se eseguo un'azione da quella pagina, devo elaborarla in qualche modo e poi reindirizzare alla pagina senza il parametro dell'azione. Non importa se uso GET o POST.

Su tutte le sue pagine interne, WordPress fa questo sulla stessa pagina: controlla se c'è un'azione, in caso affermativo la elabora e poi reindirizza a se stesso senza l'azione. Questo è possibile perché su queste pagine l'admin-header non è stato ancora caricato.

Se provi a farlo sulla tua pagina personalizzata, però, metà dell'interfaccia di amministrazione è già stata inviata al browser, quindi un redirect non è più possibile. Chiaramente, la soluzione è fare POST/GET direttamente su un'altra pagina, caricare il framework WP su quella, eseguire l'elaborazione e poi reindirizzare alla pagina originale... ma... è un po' fastidioso, perché... la mia pagina originale viene caricata tramite una callback, quindi viene eseguita all'interno di un metodo della mia classe. Questo è bellissimo.

Se carico una pagina separata, devo includere manualmente wp-load.php e mi trovo fuori dalla mia classe, il che è fastidioso, e nel mio caso particolare mi infastidisce particolarmente, perché sto istanziando la mia classe del plugin in modo anonimo in modo che nessuno possa accedervi dall'esterno.

Quindi dopo questa lunga storia... qualcuno ha trovato una buona soluzione per caricare un'altra pagina tramite callback senza avere già configurata l'intera interfaccia di amministrazione intorno ad essa?

(Conosco una soluzione alternativa... posso agganciare una funzione a load-.... che controlla il parametro dell'azione ed esegue l'elaborazione e il redirect. Ma mi chiedo se esiste un modo migliore.)

Grazie.

4
Commenti

Perché è stato etichettato con [plugin-wp-pagenavi]? [plugin-development] è certamente benvenuto qui.

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

@Jan Fabry: Non sono sicuro a cosa serva plugin-wp-pagenavi... pensavo fosse per questioni relative alla correlazione tra plugin e menu di amministrazione. Dato che la mia domanda è correlata a questo, ho selezionato quel tag.

wyrfel wyrfel
1 mar 2011 00:11:43

WP-PageNavi è un plugin con una navigazione di paginazione più avanzata per il front-end. Potresti usare [admin-menu] qui, ma non credo sia davvero correlato a quello. Ho cambiato i tag con quelli che ritengo più appropriati, puoi ovviamente modificarli di nuovo.

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

@Jan Fabry: Grazie per il re-tagging... non sono ancora molto familiare con l'intero pool di tag, a quanto pare.

wyrfel wyrfel
1 mar 2011 11:52:10
Tutte le risposte alla domanda 3
7
32

Come regola generale, dovresti utilizzare una richiesta POST per la maggior parte delle azioni, per assicurarti che non vengano eseguite accidentalmente. È anche una buona pratica reindirizzare a una pagina normale dopo una richiesta POST, per evitare esecuzioni duplicate quando l'utente aggiorna la pagina.

Quindi il flusso è il seguente:

  1. La pagina del tuo plugin con un modulo POST, che invia a
  2. Una pagina che gestisce la richiesta, che reindirizza a
  3. La pagina del tuo plugin, che mostra il risultato dell'azione

La pagina intermedia non deve essere necessariamente quella del tuo plugin. Ciò significa che puoi utilizzare il "gestore POST generico" incluso tre anni fa, l'hook 'admin_action_' . $_REQUEST['action'] in admin.php.

Un esempio di utilizzo è il plugin Akismet. Se vuoi usarlo in modo affidabile, devi inviare direttamente a admin.php, non a un'altra pagina che include casualmente admin.php.

Ecco un esempio molto basilare di come utilizzarlo:

add_action( 'admin_action_wpse10500', 'wpse10500_admin_action' );
function wpse10500_admin_action()
{
    // Fai le tue operazioni qui

    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="Esegui!" />
</form>
<?php
}
28 feb 2011 23:08:50
Commenti

Ehi, guarderò di nuovo il codice, ovviamente non l'avevo notato, ma solo per confermare...quindi quello che stai dicendo è che se chiamo admin.php direttamente senza un parametro page, salta tutto il caricamento della pagina e fa solo qualche inizializzazione e esegue l'hook? Sarebbe fantastico... più o meno (ancora non capisco perché non hanno messo l'hook prima del caricamento della pagina).

wyrfel wyrfel
1 mar 2011 00:27:51

@wyrfel: Sì, chiamare admin.php direttamente è il "trucco" che mi ha insegnato il codice sorgente di Akismet. Hai ragione quando stai visualizzando un form e vuoi visualizzarlo di nuovo in caso di errori: allora sarebbe facile se la destinazione è la tua pagina del plugin ma l'hook è da qualche parte all'inizio (così potresti reindirizzare se ha successo, o visualizzare di nuovo il form con i messaggi di errore se no). Magari suggeriscilo in un ticket Trac?

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

Aprirò un ticket. Come soluzione alternativa, ho scoperto che l'hook 'load-<pagehook>' funziona...viene chiamato prima che la pagina venga caricata...ma il concetto di admin_action_... sembra molto più carino e specifico. Inoltre, nota a margine, i messaggi di errore sono ancora problematici se fai POST e non vuoi ripostare al ricaricamento, ma questo è un altro argomento.

wyrfel wyrfel
1 mar 2011 11:50:03

@wyrfel: Perché i messaggi di errore sarebbero ancora problematici? Se c'è un messaggio di errore, rimani sulla pagina e mostra nuovamente il modulo con i messaggi (ovviamente un refresh qui non avrebbe molto senso - ma non farebbe nemmeno male, perché gli errori sarebbero ancora presenti e nessuna azione verrà eseguita). Se non ci sono errori, esegui l'azione e reindirizza a una pagina di panoramica "sicura". Questo funzionerebbe - se l'hook admin_action_ fosse spostato prima del caricatore della pagina del plugin.

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

Ok... stavo pensando in modo troppo complicato.

wyrfel wyrfel
1 mar 2011 12:57:14

Ho esteso questo post e abilitato questi stessi metodi 'admin-action' per essere chiamati da URL 'post-row-action'. La soluzione utilizza Jquery per mappare un URL GET alla richiesta POST del FORM che questa risposta affronta. 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

Per garantire la sicurezza, dovresti generare un nonce nel modulo utilizzando wp_nonce_field, e verificare il nonce nel gestore dell'azione usando wp_verify_nonce.

Flimm Flimm
2 set 2020 16:25:17
Mostra i restanti 2 commenti
1

Ho affrontato questo in modo leggermente diverso aggiungendo semplicemente noheader=true all'URL dell'azione nella pagina dove l'utente invia l'azione.

Il mio gestore esegue quindi l'azione (ad esempio tipicamente un'aggiunta, un aggiornamento o un'eliminazione) e termina con un wp_redirect() alla successiva azione della pagina (es. pagina di aggiunta -> pagina di modifica, pagina di eliminazione -> pagina di elenco, pagina di modifica -> pagina di modifica). Inoltre passo un messaggio nell'URL così da poter visualizzare uno stato come aggiornamento riuscito o fallito.

Questo approccio mantiene tutte le azioni: elenco, aggiunta, modifica, eliminazione, eliminazione multipla, ecc. nella stessa classe e con lo stesso slug di amministrazione, rendendolo abbastanza facile da mantenere e da comprendere.

29 ago 2011 15:22:57
Commenti

Ragazzo, sei un genio! Ho lottato per due giorni di fila e alla fine tutto ciò di cui avevo bisogno era la parte "noheader=true". Grazie!

roman roman
9 apr 2014 13:37:43
0

Un altro approccio diverso è semplicemente aggiungere un campo input nascosto al form:

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

In questo modo, WordPress sembra gestire automaticamente il reindirizzamento.

16 gen 2015 18:02:23