Wie gehe ich am besten mit benutzerdefinierten Pluginseitenaktionen um?


21

Ich bin ständig auf die gleiche Störung gestoßen, also dachte ich, ich würde sehen, ob es da draußen irgendwelche Ideen oder Erfahrungen gibt ...

Ich habe ein Plugin erstellt, das eine eigene Admin-Seite verwendet. Es muss. Jetzt, wo ich das WP_List_Table () - Zeug aussortiert habe, muss ich sagen, dass es großartig ist ... aber ...

Benutzerdefinierte Pluginseiten werden immer geladen, es admin.php?page=...sei denn, ich möchte sie direkt aus dem Plugin-Verzeichnis laden, was ich nicht tue. Wenn ich nun von dieser Seite aus eine 'Aktion' mache, muss ich das irgendwie verarbeiten und dann ohne den Aktionsparameter zurück auf die Seite leiten . Egal ob ich ein GET oder POST mache, wirklich.

Auf allen internen Seiten von WP wird dies auf derselben Seite ausgeführt. Es wird überprüft, ob eine Aktion vorhanden ist. Wenn dies der Fall ist, wird sie verarbeitet und ohne die Aktion an sich selbst weitergeleitet. Dies ist möglich, da auf diesen Seiten die admin-headernoch nicht geladen wurden.

Wenn Sie es jedoch auf Ihrer eigenen Seite versuchen, wurde bereits die Hälfte der Administrationsoberfläche an den Browser gesendet, sodass eine Weiterleitung nicht mehr möglich ist. Natürlich besteht die Lösung darin, direkt auf eine andere Seite zu POSTEN / GETEN, das WP-Framework darauf zu laden, die Verarbeitung durchzuführen und dann zur ursprünglichen Seite zurückzukehren ... aber ... das ist ein bisschen ärgerlich, weil ... mein Original Die Seite wird über einen Rückruf geladen, sodass sie innerhalb einer Methode meiner Klasse ausgeführt wird. Das ist schön.

Wenn ich eine separate Seite lade, muss ich manuell einschließen wp-load.phpund bin außerhalb meiner Klasse, was ärgerlich ist, und in meinem speziellen Fall nervt es mich besonders, weil ich meine Plugin-Klasse nur anonym instanziiere, damit niemand darauf zugreifen kann von außen.

Also, nach dieser langen Geschichte ... hat jemand eine gute Lösung gefunden, um eine andere Seite über einen Rückruf zu laden, ohne dass die gesamte Administrationsoberfläche bereits eingerichtet ist?

(Ich kenne eine Problemumgehung ... Ich kann eine Funktion load-....einbinden, die nach dem Aktionsparameter sucht und die Verarbeitung und Umleitung durchführt. Aber ich frage mich, ob es einen besseren Weg gibt.)

Vielen Dank.


Warum ist das mit markiert [plugin-wp-pagenavi]? [plugin-development]ist hier sicher willkommen.
Jan Fabry

@Jan Fabry: Ich bin mir nicht sicher, wofür es plugin-wp-pagenaviist ... ich habe angenommen, dass es um die Korrelation zwischen Plugins und dem Admin-Menü geht. Da meine Frage damit zusammenhängt, habe ich diesen Tag ausgewählt.
Wyrfel

WP-PageNavi ist ein Plugin mit einer erweiterten Paging-Navigation für das Frontend. Du könntest es [admin-menu]hier gebrauchen , aber ich glaube nicht, dass es wirklich damit zusammenhängt. Ich habe die Tags so geändert, wie ich es für passend halte. Sie können sie natürlich wieder bearbeiten.
Jan Fabry

@Jan Fabry: Danke für das Umetikettieren ... noch nicht so vertraut mit dem gesamten Tag-Pool (ganz offensichtlich).
Wyrfel

Antworten:


28

Als Faustregel sollten Sie für die meisten Aktionen eine POST-Anforderung verwenden, um sicherzustellen, dass sie nicht versehentlich ausgeführt werden . Es empfiehlt sich jedoch auch, nach einer POST-Anforderung auf eine normale Seite umzuleiten, um eine doppelte Ausführung zu verhindern, wenn der Benutzer die Seite aktualisiert.

Der Ablauf sieht also so aus:

  1. Ihre Plugin-Seite mit einem POST-Formular, das an übermittelt wird
  2. Eine Seite, die die Anforderung verarbeitet, zu der umgeleitet wird
  3. Ihre Plugin-Seite, die das Ergebnis der Aktion anzeigt

Die mittlere Seite muss nicht Ihre Pluginseite sein. Das bedeutet, dass Sie mit dem "generischen POST-Handler" , der vor drei Jahren mitgeliefert wurde, das 'admin_action_' . $_REQUEST['action']Hook-In durchführen könnenadmin.php .

Ein Beispielbenutzer ist das Akismet-Plugin . Wenn Sie es zuverlässig verwenden möchten, müssen Sie es admin.phpdirekt an senden und nicht an eine andere Seite, die es zufällig enthält admin.php.

Hier ist ein sehr einfaches Beispiel, wie man es benutzt:

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
}

Hei, ich werde mir den Code noch einmal ansehen, das habe ich natürlich nicht gesehen, aber nur zur Bestätigung ... Sie sagen also, wenn ich admin.php direkt ohne Seitenparameter aufrufe, werden alle Seiten übersprungen laden und nur etwas initialisieren und den hook laufen lassen? Das wäre großartig ... ish (ich verstehe immer noch nicht, warum sie den Haken nicht vor dem Laden der Seite gesetzt haben).
Wyrfel

@wyrfel: Ja, admin.phpdirekt anzurufen ist der "Trick", den mir die Akismet-Quelle beigebracht hat. Sie haben Recht, wenn Sie ein Formular anzeigen und es im Fehlerfall erneut anzeigen möchten: Dann wäre es einfach, wenn das Ziel Ihre Pluginseite, aber der Hook irgendwo am Anfang ist (Sie könnten also bei Erfolg umleiten oder das anzeigen) Wenn nicht, bitte erneut mit Fehlermeldungen ausfüllen. Vielleicht in einem Trac-Ticket vorschlagen?
Jan Fabry

Ich werde ein Ticket einreichen. Als Workaround habe ich festgestellt, dass der 'load-<pagehook>'Hook funktioniert ... er wird aufgerufen, bevor die Seite geladen wird ... aber das admin_action_...Konzept scheint viel netter und spezifischer zu sein. Außerdem sind die Fehlermeldungen nach wie vor problematisch, wenn Sie POSTs durchführen und beim erneuten Laden keine Neuveröffentlichung vornehmen möchten, aber das ist ein anderes Thema.
Wyrfel

@wyrfel: Warum sollten Fehlermeldungen immer noch problematisch sein? Wenn es eine Fehlermeldung gibt, bleiben Sie auf der Seite und zeigen Sie das Formular erneut mit den Meldungen an (eine Aktualisierung wäre hier natürlich nicht sinnvoll - aber es würde auch keinen Schaden anrichten, da die Fehler immer noch vorhanden wären und keine Aktion ausgeführt wird ausgeführt werden). Wenn keine Fehler vorliegen, führen Sie die Aktion aus und leiten Sie zu einer "sicheren" Übersichtsseite weiter. Dies würde funktionieren - wenn der admin_action_Haken vor dem Plugin-Seitenlader verschoben würde.
Jan Fabry

Ok ... ich dachte zu kompliziert.
Wyrfel

3

Ich habe dies etwas anders angegangen, indem ich der Aktions-URL auf der Seite, auf der der Benutzer die Aktion durchführt, einfach noheader = true hinzugefügt habe

Mein Handler führt dann die Aktion aus (dh normalerweise ein Hinzufügen, Aktualisieren oder Löschen) und endet dann mit einem wp_redirect () zur nächsten Seitenaktion (z. B. Seite hinzufügen -> Seite bearbeiten, Seite löschen -> Listenseite, Seite bearbeiten -> Seite bearbeiten) ). Ich übergebe auch eine Nachricht an die URL, damit ich einen Status wie "Aktualisierung erfolgreich" oder "Fehlgeschlagen" anzeigen kann.

Dieser Ansatz behält alle Aktionen bei: Auflisten, Hinzufügen, Bearbeiten, Löschen, Massenlöschen usw. in derselben Klasse und mit demselben Administrations-Slug, so dass es ziemlich einfach zu warten und zu verstehen ist.


Mann, du bist ein Genie! Ich habe seit zwei aufeinanderfolgenden Tagen Probleme und es scheint, dass alles, was ich brauchte, der Teil "noheader = true" war. Vielen Dank!
R00M

0

Ein anderer Ansatz ist das Hinzufügen eines ausgeblendeten Eingabefelds zum Formular:

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

Auf diese Weise scheint WordPress die Umleitung automatisch zu handhaben.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.