3 Ansätze zum Hinzufügen konfigurierbarer Felder zu Ihrem WordPress-Plugin
Veröffentlicht: 2022-03-10Jeder, der ein WordPress-Plugin erstellt hat, versteht die Notwendigkeit, konfigurierbare Felder zu erstellen, um die Funktionsweise des Plugins zu ändern. Es gibt unzählige Verwendungsmöglichkeiten für konfigurierbare Optionen in einem Plugin und fast ebenso viele Möglichkeiten, diese Optionen zu implementieren. Sie sehen, WordPress erlaubt Plugin-Autoren, ihr eigenes Markup auf ihren Einstellungsseiten zu erstellen. Als Nebeneffekt können die Einstellungsseiten zwischen den Plugins stark variieren.
In diesem Artikel gehen wir auf drei gängige Möglichkeiten ein, wie Sie Ihr Plugin konfigurierbar machen können. Wir beginnen mit dem Erstellen einer Einstellungsseite und erstellen unsere Felder mit der standardmäßigen WordPress-Einstellungs-API.
Weiterführende Literatur zu SmashingMag:
- Erweitern Sie WordPress mit benutzerdefinierten Feldern
- Hacks für benutzerdefinierte Felder für WordPress
- Erweitern Sie erweiterte benutzerdefinierte Felder mit Ihren eigenen Steuerelementen
- Der vollständige Leitfaden zu benutzerdefinierten Beitragstypen
Ich werde Sie dann durch die Einrichtung Ihrer Felder mit einem benutzerdefinierten Handler führen. Abschließend zeige ich Ihnen, wie Sie ein großartiges Plugin für konfigurierbare Felder, Advanced Custom Fields (ACF), in Ihr eigenes Plugin integrieren können.
Da dies ein langer Beitrag ist, finden Sie hier ein Inhaltsverzeichnis mit Links zu den einzelnen Hauptabschnitten:
- Erstellen unserer Plugin- und Einstellungsseite
- Ansatz 1: Verwenden der integrierten WordPress-Funktionalität
- Ansatz 2: Einrichten eines benutzerdefinierten Formulars und Handlers
- Ansatz 3: Integrieren von ACF (Advanced Custom Fields) in Ihr Plugin
Codebeispiele finden Sie in dem Repository, das ich eingerichtet habe, um diesen Beitrag zu begleiten.
Erstellen unserer Plugin- und Einstellungsseite
Als erstes müssen wir unser Plugin einrichten und eine Einstellungsseite erstellen. Alle drei in diesem Artikel beschriebenen Ansätze beginnen mit der folgenden Plugin-Struktur. Diese Plugin-Struktur ist objektorientiert , daher kann es einige Unterschiede in Ihrem eigenen Code geben, wenn Ihr Plugin prozedural geschrieben ist. Achten Sie besonders auf das Callback-Funktionsformat in den Aktionen und Filtern.
/* Plugin Name: Smashing Fields Plugin description: >- Setting up configurable fields for our plugin. Author: Matthew Ray Version: 1.0.0 */ class Smashing_Fields_Plugin { // Our code will go here } new Smashing_Fields_Plugin();
In unserer Klasse werden wir einen Aktionshaken hinzufügen, um die Einstellungsseite hinzuzufügen:
public function __construct() { // Hook into the admin menu add_action( 'admin_menu', array( $this, 'create_plugin_settings_page' ) ); }
Sie können sehen, dass der Callback unserer Aktion create_plugin_settings_page
ist, also erstellen wir diese Methode. Hinweis: Ich habe die Argumente als separat benannte Variablen eingerichtet, um unserem Code etwas Kontext zu geben, aber Sie können die Werte einfach direkt in die Funktion einfügen, um Speicher zu sparen.
public function create_plugin_settings_page() { // Add the menu item and page $page_title = 'My Awesome Settings Page'; $menu_title = 'Awesome Plugin'; $capability = 'manage_options'; $slug = 'smashing_fields'; $callback = array( $this, 'plugin_settings_page_content' ); $icon = 'dashicons-admin-plugins'; $position = 100; add_menu_page( $page_title, $menu_title, $capability, $slug, $callback, $icon, $position ); }
Weitere Informationen finden Sie im WP-Codex für add_menu_page
.
Diese Funktion erstellt sowohl unsere Seite als auch den Menüpunkt. Die wichtigen Teile hier sind die Slug-, Capability- und Callback-Argumente. Den Slug werden wir später verwenden, um unsere Felder zu registrieren, also notieren Sie sich das irgendwo. Sie können die Möglichkeit ändern, verschiedenen Benutzerebenen Zugriff auf Ihre Einstellungsseite zu gewähren. Was den Rückruf betrifft, werden wir diese Methode in Kürze erstellen. Beachten Sie, dass Sie auch eine Dashicon-Klasse direkt in die Funktion einfügen können, um das Symbol für das Menü zu ändern. Das letzte Argument ist die Position des Menüpunkts innerhalb des Menüs; Spielen Sie mit dieser Nummer herum, um die Stelle im Menü zu finden, an der Ihre Einstellungen fallen sollen. Hinweis: Sie können Dezimalwerte verwenden, um Konflikte mit anderen Menüpunkten zu vermeiden.
Als Nächstes erstellen wir die Callback-Methode plugin_settings_page_content
für unsere Einstellungsseite.
public function plugin_settings_page_content() { echo 'Hello World!'; }
Wenn Sie Ihr Plugin speichern und das WordPress-Admin-Panel aktualisieren, sollten Sie Folgendes sehen:

Sie können sehen, dass Ihre Einstellungsseite ein Menüelement der obersten Ebene ist. Sie können es je nach den Anforderungen Ihrer Einstellungsseite lieber so belassen. Möglicherweise möchten Sie Ihre Plugin-Einstellungen jedoch auch unter einem anderen Menüpunkt haben. In diesem Fall ändern Sie einfach die letzte Zeile der Methode create_plugin_settings_page
wie folgt:
add_submenu_page( 'options-general.php', $page_title, $menu_title, $capability, $slug, $callback );
Hier ändern wir die Funktion add_menu_page
in add_submenu_page
und stellen ein neues Argument voran. Dieses Argument ist das übergeordnete Menüelement, unter dem sich die neue Einstellungsseite befinden wird. In der add_submenu_page
Dokumentation können Sie eine ziemlich gute Liste für die übergeordneten Menüelemente und ihre Slugs sehen. Sie werden vielleicht auch sehen, dass wir die letzten beiden Argumente $icon
und $position
nicht mehr haben. Da wir uns nun im Untermenübereich befinden, haben wir keine Kontrolle mehr über die Position des Elements. Außerdem sind für Untermenüs keine Symbole verfügbar, sodass dieses Argument nicht erforderlich ist.
Wenn Sie diesen neuen Code speichern, sehen Sie, dass unsere Einstellungsseite unter dem Menüpunkt Einstellungen angezeigt wird:

In vielen Fällen ist der am besten geeignete Ort zum Hinzufügen einer Plugin-Einstellungsseite unter dem Element Einstellungen. Im WordPress-Codex wird erklärt, dass der Abschnitt „Einstellungen“ verwendet wird, um „Plugin-Optionen anzuzeigen, die nur Administratoren anzeigen sollten“. Dies ist jedoch nur eine Richtlinie, keine Regel.
Nachdem wir nun unsere Einstellungsseite eingerichtet haben und wissen, wie die Elemente verschoben werden, können wir mit der Arbeit an den Feldern beginnen. Die bisher geleistete Arbeit wird für die verschiedenen folgenden Methoden wiederverwendet.
Ansatz 1: Verwenden der integrierten WordPress-Funktionalität
Bevor wir zu tief in den Code einsteigen, gehen wir einige der Vor- und Nachteile dieses Ansatzes durch.
Vorteile
- Einfache Integration in bestehende Einstellungsseiten
- Die Desinfektion wird für Sie durchgeführt
- Es ist unwahrscheinlich, dass es kaputt geht, da der Code von WordPress verwaltet wird
- Kann sowohl für Themes als auch für Plugins verwendet werden
- Flexibel, sicher und erweiterbar
Nachteile
- Die benutzerdefinierte Datenvalidierung erfolgt manuell
- Erweiterte Feldtypen (Repeater, Maps, Uploads usw.) sind schwieriger zu implementieren
Wann sollten Sie diesen Ansatz verwenden?
Dieser Ansatz ist so flexibel, dass er für sehr einfache oder sehr erweiterte Einstellungsseiten angepasst werden kann. Sie können diese Methode in den meisten Situationen verwenden, wenn es Ihnen nichts ausmacht, einige Dinge manuell zu erledigen.
Einstieg
Bei diesem Ansatz müssen wir dem gleichen Markup folgen, das die eigenen Optionsseiten von WordPress verwenden. Wir sollten unsere Methode plugin_settings_page_content
wie folgt ändern:
public function plugin_settings_page_content() { ?> <div class="wrap"> <h2>My Awesome Settings Page</h2> <form method="post" action="options.php"> <?php settings_fields( 'smashing_fields' ); do_settings_sections( 'smashing_fields' ); submit_button(); ?> </form> </div> <?php }
Das obige Markup stammt direkt aus dem WordPress-Codex zum Erstellen von Optionsseiten. Der Methodenname sollte mit dem Callback-Namen übereinstimmen, den wir oben in die Funktion add_menu_page
. Das Wrapper div
ist eigentlich dasselbe wie ein Standard-WordPress-Formular und zieht die Stile aus diesen Abschnitten ein. Das form
-Tag zeigt auf den Standardoptions-Form-Handler für WordPress.
Die drei Zeilen von PHP machen mehrere Dinge:
- Die Funktion
settings_fields
ist im Grunde eine Referenz für den Rest unserer Felder. Das String-Argument, das Sie in diese Funktion einfügen, sollte mit der$slug
Variable übereinstimmen, die wir zuvor eingerichtet haben – es wird in allen Feldern enthalten sein, die wir später im Plugin registrieren. Diese Funktion gibt auch einige versteckte Eingaben für die Nonce, die Formularaktion und einige andere Felder für die Optionsseite aus. - Die nächste Funktion,
do_settings_sections
, ist ein Platzhalter für die Abschnitte und Felder, die wir an anderer Stelle in unserem Plugin registrieren werden. - Die letzte Funktion,
submit_button
, gibt die Submit-Eingabe aus, fügt aber auch einige Klassen basierend auf dem Status der Seite hinzu. Möglicherweise gibt es noch andere Argumente, die Sie an die Funktionsubmit_button
übergeben möchten; sie sind im Codex umrissen.
Wenn wir unsere Einstellungsseite aktualisieren, sollten wir etwas erhalten, das so aussieht:

Es sieht etwas spärlich aus! Beginnen wir jetzt mit der Einrichtung der Felder.
Abschnitte und Felder
WordPress unterteilt seine Optionsseiten in Abschnitte. Jedem Abschnitt kann eine Liste von Feldern zugeordnet sein. Wir müssen einen Abschnitt in unserem Plugin registrieren, bevor wir mit dem Hinzufügen unserer Felder beginnen können. Fügen Sie Ihrer Konstruktorfunktion den folgenden Code hinzu:
add_action( 'admin_init', array( $this, 'setup_sections' ) );
Dieser Hook richtet die Abschnitte für unsere Seite ein. Hier der Code für den Rückruf:
public function setup_sections() { add_settings_section( 'our_first_section', 'My First Section Title', false, 'smashing_fields' ); }
Das erste Argument ist ein eindeutiger Bezeichner für den Abschnitt, den wir für die Felder verwenden, die wir dem Abschnitt zuweisen möchten. Diese Kennungen sollten für alle neuen Abschnitte auf dieser Seite eindeutig sein. Das nächste Argument ist der Titel, der über dem Abschnitt generiert wird – Sie können ihn beliebig gestalten. Das dritte Argument ist der Rückruf. Im Moment habe ich es auf false
gesetzt, aber wir werden dies in Kürze wiederholen. Das vierte Argument ist die Optionsseite, zu der die Optionen hinzugefügt werden (die $slug
Variable von früher).
Warum ist unser Rückruf false
? Nun, etwas, das beim Einrichten von WordPress-Optionen mithilfe ihrer Dokumentation nicht ganz klar ist, ist, dass mehrere Abschnitte einen Callback teilen können. Wenn Sie einen Rückruf einrichten, besteht häufig eine 1-zu-1-Beziehung zwischen dem Haken und dem Rückruf. Versuchen wir also nur als Beispiel, drei Abschnitte mit demselben Callback zu erstellen:
public function setup_sections() { add_settings_section( 'our_first_section', 'My First Section Title', array( $this, 'section_callback' ), 'smashing_fields' ); add_settings_section( 'our_second_section', 'My Second Section Title', array( $this, 'section_callback' ), 'smashing_fields' ); add_settings_section( 'our_third_section', 'My Third Section Title', array( $this, 'section_callback' ), 'smashing_fields' ); }
Alle drei dieser Abschnitte haben den Callback section_callback
in diesem dritten Argumentslot gesetzt. Wenn wir dann eine Methode erstellen, die diesem Callback entspricht, und dort ein „Hello World“ einfügen:
public function section_callback( $arguments ) { echo '
Hallo Welt
'; }
wir bekommen etwas, das so aussieht:

Ich weiß, was Sie denken: „Warum zum Teufel sollte ich in allen meinen Abschnitten denselben Text haben wollen?“ Die Antwort ist, dass Sie es wahrscheinlich nicht tun würden. Hier können wir mit der Funktion add_settings_section
etwas knifflig werden. Wenn Sie sich die Dokumentation für diese Funktion ansehen, werden Sie sehen, dass der Callback-Funktion im Notes -Teil der Seite ein Array von Argumenten zugewiesen wird, die direkt mit den Argumenten in unserem Hook korrelieren. Wenn Sie hineingehen und var_dump( $arguments )
, sehen Sie alle Argumente, die an unsere Funktion übergeben werden.
Wir können dann einen einfachen Schalter in unseren Rückruf schreiben, um den Text basierend auf der darin übergebenen ID zu ändern:
public function section_callback( $arguments ) { switch( $arguments['id'] ){ case 'our_first_section': echo 'This is the first description here!'; break; case 'our_second_section': echo 'This one is number two'; break; case 'our_third_section': echo 'Third time is the charm!'; break; } }
Jetzt haben wir benutzerdefinierten Text für jeden Abschnitt, den wir in einer Funktion ändern können!

Natürlich können Sie auch eindeutige Rückrufe für diese Abschnitte angeben, aber dieser Ansatz ermöglicht es Ihnen, Ihren Code in einer einzigen Funktion zu konsolidieren. Diese Idee funktioniert genauso beim Einrichten von Feldern. Wir können alle unsere Felder einen Callback teilen lassen und ihn basierend auf den übergebenen Argumenten den richtigen Feldtyp ausgeben lassen. Lassen Sie uns die Felder zu unserer Konstruktormethode hinzufügen. Fügen Sie diesen Code direkt nach unserem Abschnitts-Hook im Konstruktor ein:
add_action( 'admin_init', array( $this, 'setup_fields' ) );
Da Sie die Übung bereits kennen, gebe ich Ihnen nur den Rückruf für unsere Aktion:
public function setup_fields() { add_settings_field( 'our_first_field', 'Field Name', array( $this, 'field_callback' ), 'smashing_fields', 'our_first_section' ); }
Die Argumente in dieser Funktion ähneln denen in der Abschnittsfunktion. Das erste Argument ist der eindeutige Bezeichner für das Feld. Das zweite ist das Etikett, das neben dem Feld angezeigt wird. Im dritten Argument sehen Sie, dass ich die Methode field_callback
; Wir erstellen diesen Rückruf in nur einer Sekunde. Die vierte ist die Optionsseite, die wir verwenden möchten (unser $slug
von früher). Das fünfte Argument ist die eindeutige Kennung für den Abschnitt , dem wir dieses Feld zuweisen möchten.
Hier ist der Code für den Rückruf in unserem dritten Argument:
public function field_callback( $arguments ) { echo '<input name="our_first_field" type="text" value="' . get_option( 'our_first_field' ) . '" />'; }
Hier kopiere ich einfach die eindeutige Kennung des Felds in den Namen, die ID und unsere get_option
Funktion. Mal sehen, wie unsere Seite mit unserem neuen Feld aussieht:

Großartig, wir haben unser Feld auf der Seite! Versuchen Sie, etwas Inhalt hinzuzufügen und auf Änderungen speichern zu klicken, ich warte hier ...
Hast du es getan? Wenn Sie bis zu diesem Punkt alles richtig gemacht haben, sollten Sie eine Fehlermeldung wie ERROR: options page not found
oder ähnliches erhalten haben. Der Grund dafür ist eigentlich eine Sicherheitsfunktion in WordPress.
Sie sehen, ohne diese Funktion könnte ein Benutzer in den HTML-Code gehen und den Namen eines Felds beliebig ändern, auf Speichern klicken, und diese Option würde mit dem angegebenen Namen in die Datenbank eingegeben (vorausgesetzt, es wäre eine gültige Optionsname). Dies könnte es jedem Benutzer ermöglichen, Optionen auf anderen Seiten zu ändern (sogar auf Seiten, auf die er normalerweise nicht zugreifen kann), indem er einfach den richtigen Namen in das Feld eingibt und auf Speichern klickt – nicht cool.
Dieses Problem wird durch Hinzufügen einer Funktion namens register_setting
gelöst. Sofern Sie WordPress nicht ausdrücklich sagen: „Hey, dieses Feld darf auf dieser Seite gespeichert werden“, aktualisiert WordPress kein Feld in der Datenbank. Unter unserem Feld-Markup fügen wir also diese neue Funktion hinzu. So sieht der Callback aus, nachdem wir den Code hinzugefügt haben:
public function field_callback( $arguments ) { echo '<input name="our_first_field" type="text" value="' . get_option( 'our_first_field' ) . '" />'; register_setting( 'smashing_fields', 'our_first_field' ); }
Das erste Argument in der neuen Funktion ist die Optionsseite, auf der wir das Feld speichern möchten (das $slug
von früher), und das zweite Argument ist das Feld, das wir speichern möchten. Versuchen Sie nun, das Feld zu aktualisieren – es hat funktioniert!
Glückwünsche! Sie haben gerade Ihr erstes Feld mit der WordPress-Einstellungs-API gespeichert. Was ist nun, wenn wir anstelle von Text verschiedene Feldtypen haben möchten? Sehen wir uns noch einmal unseren Feld-Callback an und sprechen wir über die $arguments
Variable, die an unsere Funktion übergeben wird.
Feldargumente
Wenn wir in unser Feld Callback und var_dump( $arguments )
gehen, erhalten wir ein leeres Array. Was gibt? In unserem Sektionsrückruf haben wir eine Menge Zeug über die Sektion bekommen. Nun, hier geht es um etwas anderes. Wenn Sie sich die Dokumentation für add_settings_field
, gibt es ein fünftes Argument, das an die Funktion übergeben werden kann. Diese Variable korreliert direkt mit der $arguments
Variablen in unserem Callback. Also wollen wir unsere neuen Sachen dort reinstellen.
Wenn wir uns eines der Standardfelder auf einer WordPress-Einstellungsseite ansehen, sehen wir, dass es mehrere Bereiche gibt, die wir zu unserem Feld hinzufügen können, um eine Standardformatierung zu erhalten. Hier ist ein Screenshot des Zeitzonenfelds auf der Seite mit den allgemeinen Einstellungen:

Mit diesem Feld als Ausgangspunkt gehen wir die Daten durch, die wir an unseren Feldrückruf übergeben möchten.
- Die eindeutige Kennung
- Die Bezeichnung für das Feld (Zeitzone im Beispiel)
- In welche Rubrik soll es gehen
- Der Feldtyp (Text, Textbereich, Auswahl usw.)
- Falls es mehrere Optionen gibt, wollen wir diese
- Vielleicht ein Platzhalter, wenn der Feldtyp einen unterstützt
- Hilfstext (im Beispiel rechts neben dem Feld)
- Zusatztext (im Beispiel unter dem Feld)
- Vielleicht eine Standardauswahl, wenn es eine gibt
Aus dieser Liste können wir ein assoziatives Array von Feldern und Werten einrichten, die wir an unseren Callback übergeben können:
public function setup_fields() { $fields = array( array( 'uid' => 'our_first_field', 'label' => 'Awesome Date', 'section' => 'our_first_section', 'type' => 'text', 'options' => false, 'placeholder' => 'DD/MM/YYYY', 'helper' => 'Does this help?', 'supplemental' => 'I am underneath!', 'default' => '01/01/2015' ) ); foreach( $fields as $field ){ add_settings_field( $field['uid'], $field['label'], array( $this, 'field_callback' ), 'smashing_fields', $field['section'], $field ); register_setting( 'smashing_fields', $field['uid'] ); } }
Das erste, was wir hier haben, ist eine Variable namens $fields
, die alle Felder enthält, die wir erstellen möchten. Innerhalb dieses Arrays haben wir ein weiteres Array, das die spezifischen Daten für jedes Feld enthält. Ich habe die Daten so eingestellt, dass sie genau mit unserer obigen Liste übereinstimmen. Dann durchlaufe ich jedes Feld (wir werden in Kürze weitere hinzufügen) im Array und füge das Feld hinzu und registriere es. Am Ende der add_settings_field
Funktion füge ich auch das gesamte Datenarray für dieses spezifische Feld hinzu, damit wir einige Dinge in der Callback-Funktion tun können. Schauen wir uns diese Callback-Funktion hier an:
public function field_callback( $arguments ) { $value = get_option( $arguments['uid'] ); // Get the current value, if there is one if( ! $value ) { // If no value exists $value = $arguments['default']; // Set to our default } // Check which type of field we want switch( $arguments['type'] ){ case 'text': // If it is a text field printf( '<input name="%1$s" type="%2$s" placeholder="%3$s" value="%4$s" />', $arguments['uid'], $arguments['type'], $arguments['placeholder'], $value ); break; } // If there is help text if( $helper = $arguments['helper'] ){ printf( '<span class="helper"> %s</span>', $helper ); // Show it } // If there is supplemental text if( $supplimental = $arguments['supplemental'] ){ printf( '<p class="description">%s</p>', $supplimental ); // Show it } }
Im obigen Beispiel machen wir mehrere Dinge. Wir legen die Standardwerte für Felder fest, wenn sie leer sind, und fügen den Hilfs- und Ergänzungstext hinzu. Der wichtigste Teil in unserem Code ist jedoch die switch-Anweisung. In dieser Anweisung werden wir skizzieren, wie unsere Argumente basierend auf dem gewünschten Feldtyp behandelt werden.
Wenn wir beispielsweise ein Textfeld haben, müssen wir nicht mehrere Optionen haben. Ein <select>
-Dropdown muss jedoch Optionen haben, um richtig zu funktionieren. Da wir bereits Texttypen eingerichtet haben, führen wir diesen Code aus und sehen, was wir bekommen.

Wenn Sie Ihre Plugin-Einstellungsseite laden, sollten Sie das obere Feld in diesem Bild sehen. Unten sehen Sie, was Sie sehen, wenn Sie den Inhalt aus dem Feld entfernen (dh den Platzhalter). Wenn ich die helper
oder supplimental
Argumente aus unserem Felder-Array entfernen würde, sollten sie auf der Einstellungsseite verschwinden. Wir können auch das section
ändern und die Platzierung des Felds in den Abschnitten verschieben.

OK, wir haben also Textfelder; Wie wäre es mit einigen komplexeren Feldtypen? Schauen wir uns unsere switch-Anweisung noch einmal an und fügen die Option für Textbereiche und Einzelauswahlen hinzu:
switch( $arguments['type'] ){ case 'text': // If it is a text field printf( '<input name="%1$s" type="%2$s" placeholder="%3$s" value="%4$s" />', $arguments['uid'], $arguments['type'], $arguments['placeholder'], $value ); break; case 'textarea': // If it is a textarea printf( '<textarea name="%1$s" placeholder="%2$s" rows="5" cols="50">%3$s</textarea>', $arguments['uid'], $arguments['placeholder'], $value ); break; case 'select': // If it is a select dropdown if( ! empty ( $arguments['options'] ) && is_array( $arguments['options'] ) ){ $options_markup = '; foreach( $arguments['options'] as $key => $label ){ $options_markup .= sprintf( '<option value="%s" %s>%s</option>', $key, selected( $value, $key, false ), $label ); } printf( '<select name="%1$s">%2$s</select>', $arguments['uid'], $options_markup ); } break; }
Im obigen Code werden Sie einige Unterschiede zwischen den einzelnen Feldtypen bemerken. Obwohl Textbereiche normalen Textfeldern funktional ähnlich sind, erfordern sie ein anderes Markup. Ausgewählte Dropdowns sind aufgrund der Optionen ein ganz anderes Tier. Wir müssen die Optionen durchlaufen und Werte, ausgewählte Zustände und Beschriftungen festlegen. Unser Markup unterscheidet sich also drastisch.
Nachdem wir unsere Callback-Funktion aktualisiert haben, sehen wir uns an, wie sich die Felddaten geändert haben:
$fields = array( array( 'uid' => 'our_first_field', 'label' => 'Awesome Date', 'section' => 'our_first_section', 'type' => 'text', 'options' => false, 'placeholder' => 'DD/MM/YYYY', 'helper' => 'Does this help?', 'supplemental' => 'I am underneath!', 'default' => '01/01/2015' ), array( 'uid' => 'our_second_field', 'label' => 'Awesome Date', 'section' => 'our_first_section', 'type' => 'textarea', 'options' => false, 'placeholder' => 'DD/MM/YYYY', 'helper' => 'Does this help?', 'supplemental' => 'I am underneath!', 'default' => '01/01/2015' ), array( 'uid' => 'our_third_field', 'label' => 'Awesome Select', 'section' => 'our_first_section', 'type' => 'select', 'options' => array( 'yes' => 'Yeppers', 'no' => 'No way dude!', 'maybe' => 'Meh, whatever.' ), 'placeholder' => 'Text goes here', 'helper' => 'Does this help?', 'supplemental' => 'I am underneath!', 'default' => 'maybe' ) );
Hier sind drei Felder, die jeweils einen anderen Feldtyp in unserem Plugin verwenden. Die erste haben wir bereits durchgegangen. Das zweite ist unser neues textarea
-Feld. Wir können die gleichen Parameter mit dem Array übergeben (mit Ausnahme der UID), aber eine einfache Änderung an unserem Typ und wir erhalten stattdessen ein textarea
. Das letzte Feld in diesem Array ist das Auswahl-Dropdown. Das wichtigste Update hier ist das Hinzufügen des Options-Arrays. Wir fügen ein einfaches assoziatives Array mit dem Array-Schlüssel als HTML-Optionswert und dem Label hinzu. Mit diesem Array sehen unsere Felder so aus:

Fast fertig!
Wir haben jetzt eine funktionierende Plugin-Einstellungsseite. Wir haben die Abschnitte für die Seite, die Optionen, alle Callbacks eingerichtet und die Felder registriert. Das einzige, was übrig bleibt, ist, unsere Einstellungswerte woanders zu bekommen. Ob Sie es glauben oder nicht, wir haben das bereits getan. Oben in unserem Feld Callback sehen Sie, dass wir nach dem Datenbankwert suchen:
$value = get_option( $arguments['uid'] );
Wir können denselben Code in unserem Plugin (oder Thema) verwenden und einfach die uid
an die Funktion übergeben. Wenn ich also den Wert von our_first_field
erhalten wollte, würde ich einfach schreiben:
get_option('our_first_field')
Hey presto! Wir haben unser tolles Plugin und unsere tollen Einstellungen! Offensichtlich haben wir nur wenige Feldtypen eingerichtet, aber ich habe das Code-Repository für diesen Ansatz durchgegangen und weitere hinzugefügt (insbesondere Textfelder, Passwörter, Zahlen, Textbereiche, Auswahl-Dropdowns, Mehrfachauswahlen, Optionsfelder und Kontrollkästchen).
Ansatz 2: Einrichten eines benutzerdefinierten Formulars und Handlers
In der Vergangenheit war dieser Ansatz die einzige Möglichkeit, Einstellungsseiten hinzuzufügen. Vor WordPress 2.7 mussten Plugin-Autoren ihre eigenen benutzerdefinierten Formulare und Handler erstellen. Dies führte offensichtlich zu vielen Fehlern und Inkonsistenzen zwischen Plugins. Obwohl dieser Ansatz etwas veraltet ist, ist er in einigen Fällen immer noch eine praktikable Option.
Vorteile
- Sie können das Formular an benutzerdefinierte und Remote-Handler senden
- Sie können einige der integrierten Einstellungen-API-Einschränkungen umgehen
Nachteile
- Die Kompatibilität muss vom Entwickler aufrechterhalten werden
- Muss manuell bereinigt und validiert werden
Wann sollten Sie diesen Ansatz verwenden?
Verwenden Sie diesen Ansatz, wenn Sie unbedingt einen benutzerdefinierten Handler oder eine stark benutzerdefinierte Schnittstelle benötigen. Wahrscheinlich kommen Sie in den meisten Fällen mit Ansatz 1 davon, aber Sie haben mit dieser Methode mehr Flexibilität bei der Validierung und Handhabung.
Einstieg
Bevor wir auf die Details eingehen, müssen wir uns ein Szenario ausdenken, in dem wir einen benutzerdefinierten Handler verwenden würden. Lassen Sie uns der Einfachheit halber ein Formular erstellen, das einen Benutzernamen und eine E-Mail-Adresse überprüft. Wir könnten die Daten aus einer Datenbank oder sogar einem Remote-Server abrufen. In diesem Fall richte ich ein Array mit gültigen Benutzernamen und E-Mail-Adressen ein, mit denen wir vergleichen können. Wir speichern dann die vom Benutzer eingegebenen Feldwerte und speichern sie in der Datenbank.
Erstellen des Formulars
Wie ich bereits erwähnt habe, werden wir die gleichen Schritte befolgen, die wir in „Erstellen unserer Plugin- und Einstellungsseite“ gemacht haben. Für diesen Ansatz richten wir unsere Felder mit statischem HTML-Markup ein. Wir fügen diesen Code wie folgt zum Callback der Funktion plugin_settings_page_content
:
public function plugin_settings_page_content() { ?> <div class="wrap"> <h2>My Awesome Settings Page</h2> <form method="POST"> <table class="form-table"> <tbody> <tr> <th><label for="username">Username</label></th> <td><input name="username" type="text" value="" class="regular-text" /></td> </tr> <tr> <th><label for="email">Email Address</label></th> <td><input name="email" type="text" value="" class="regular-text" /></td> </tr> </tbody> </table> <p class="submit"> <input type="submit" name="submit" class="button button-primary" value="Check My Info!"> </p> </form> </div> <?php }
Sie können oben sehen, dass wir nur etwas statisches HTML für unsere Felder hinzufügen. Wir duplizieren das Markup von den zentralen WordPress-Einstellungsseiten. Wir lassen auch die Formularaktion aus, damit das Formular im Gegensatz zum Standardhandler options.php an die aktuelle Seite gesendet wird.
Bevor wir unseren benutzerdefinierten Handler schreiben, fügen wir schnell einige Sicherheitsfunktionen ein. Das erste, was wir tun sollten, ist, eine Nonce in unser Formular einzufügen. Nonces schützt vor Cross-Site-Request-Fälschungsversuchen, die Benutzer-Spoofing oder Replay-Angriffen ähneln. Lassen Sie uns die Nonce in unseren HTML-Code einfügen:
<form method="POST"> <?php wp_nonce_field( 'awesome_update', 'awesome_form' ); ?> <table class="form-table">
Das wp_nonce_field
fügt unserem Formular ein paar versteckte Felder hinzu; die Nonce und der Referrer. Wir werden auf die Nonce zurückkommen, wenn wir den Handler-Code durchgehen.
Als nächstes müssen wir ein Feld hinzufügen, um zu erkennen, wann das Formular aktualisiert wurde. Wir können dies tun, indem wir einfach ein verstecktes Feld oben in unserem Formular hinzufügen:
<form method="POST"> <input type="hidden" name="updated" value="true" /> <?php wp_nonce_field( 'awesome_update', 'awesome_form' ); ?> <table class="form-table">
Jetzt können wir oben auf unserer Seite ein Code-Snippet einfügen, um zu erkennen, wann unser Formular gesendet wird, und uns an unseren benutzerdefinierten Handler senden:
public function plugin_settings_page_content() { if( $_POST['updated'] === 'true' ){ $this->handle_form(); } ?> <div class="wrap"> <h2>My Awesome Settings Page</h2>
Hier prüfen wir einfach, ob das ausgeblendete updated
Feld übermittelt wurde, und wenn dies der Fall ist, rufen wir eine Methode in unserem Plugin namens handle_form
. Hier können wir damit beginnen, unseren benutzerdefinierten Handler zu schreiben.
Handler erstellen
Es gibt ein paar Dinge, die wir im Handler überprüfen müssen, bevor wir die Formulardaten tatsächlich verwalten. Wir müssen zuerst prüfen, ob unsere Nonce existiert und gültig ist:
public function handle_form() { if( ! isset( $_POST['awesome_form'] ) || ! wp_verify_nonce( $_POST['awesome_form'], 'awesome_update' ) ){ ?> <div class="error"> <p>Sorry, your nonce was not correct. Please try again.</p> </div> <?php exit; } else { // Handle our form data } }
Der obige Code überprüft, ob die Nonce korrekt ist. Wenn es ungültig ist, geben wir dem Benutzer eine Nachricht darüber, warum das Formular nicht aktualisiert wurde. Wenn die Nonce existiert und korrekt ist, können wir mit unserem Formular umgehen. Lassen Sie uns jetzt den Code für unseren Formular-Handler schreiben (dieser Code ersetzt den Kommentar im obigen Snippet):
$valid_usernames = array( 'admin', 'matthew' ); $valid_emails = array( '[email protected]', '[email protected]' ); $username = sanitize_text_field( $_POST['username'] ); $email = sanitize_email( $_POST['email'] ); if( in_array( $username, $valid_usernames ) && in_array( $email, $valid_emails ) ){ update_option( 'awesome_username', $username ); update_option( 'awesome_email', $email );?> <div class="updated"> <p>Your fields were saved!</p> </div> <?php } else { ?> <div class="error"> <p>Your username or email were invalid.</p> </div> <?php }
Lassen Sie uns den Code in diesem Abschnitt durchgehen. Die ersten paar Zeilen sind die Arrays gültiger Benutzernamen/E-Mails, die wir überprüfen werden. Diese Array-Werte können von überall ausgefüllt werden.
Die nächsten beiden Zeilen sind die Werte, die unser Benutzer in das Formular eingegeben hat. Wir verwenden die integrierten Bereinigungsfunktionen, die WordPress uns bietet. Dieser Schritt ist wichtig, um mehrere Schwachstellen bei Webformularen zu vermeiden. Als nächstes prüfen wir, ob die von den Benutzern bereitgestellten Werte in unserem Array akzeptabler Werte enthalten sind. Wenn dies der Fall ist, aktualisieren Sie die Formularoptionen in der Datenbank. Dieser Schritt könnte auch durch einen benutzerdefinierten Speichermechanismus ersetzt werden. Wir geben dem Benutzer auch eine Nachricht, dass seine Felder gespeichert wurden. Wenn die Eingabe des Benutzers ungültig ist, teilen wir ihm dies mit.
Das letzte, was wir tun müssen, ist, die gespeicherten Felder im Formular anzuzeigen, nachdem sie eingegeben wurden. Wir werden dies auf die gleiche Weise tun, wie wir diese Felder an anderer Stelle im Plugin abrufen würden: mit der Funktion get_option
. Hier sind die Felder, nachdem wir den richtigen Code hinzugefügt haben:
<tr> <th><label for="username">Username</label></th> <td><input name="username" type="text" value="<?php echo get_option('awesome_username'); ?>" class="regular-text" /></td> </tr> <tr> <th><label for="email">Email Address</label></th> <td><input name="email" type="text" value="<?php echo get_option('awesome_email'); ?>" class="regular-text" /></td> </tr>
Jetzt sind wir bereit, unser Formular zu testen. Versuchen Sie, den Benutzernamen admin und die E-Mail-Adresse [email protected] einzugeben . Folgendes sollte auf Ihrem Formular stehen:

Wenn Sie versuchen, eines der Felder auf einen ungültigen Wert festzulegen, sollten Sie eine Fehlermeldung erhalten und die Felder sollten aufgrund unseres benutzerdefinierten Handlers nicht aktualisiert werden.
Das war's für unseren zweiten Ansatz! Sie haben jetzt ein benutzerdefiniertes Formular und einen Handler eingerichtet, um Ihre Plugin-Felder zu verwalten. Den vollständigen Code für diesen Ansatz finden Sie im Repository dieses Artikels. Kommen wir nun zu unserem endgültigen Ansatz.
Ansatz 3: Integrieren von ACF (Advanced Custom Fields) in Ihr Plugin
Wenn Sie ACF von Elliot Condon noch nicht verwendet haben, möchte ich Sie Ihnen vorstellen. ACF ist ein wunderbarer Feldmanager für WordPress. Eines der besten Dinge daran ist die Feldkonfigurationsschnittstelle. Es macht es ziemlich einfach, Felder für eine Reihe verschiedener Seiten in WordPress zu erstellen (z. B. Beiträge, Seiten, Benutzer, Taxonomien, sogar ihre eigenen integrierten Optionsseiten). Sie denken vielleicht: „Ich kann das Plugin eines anderen nicht in mein eigenes integrieren – das ist unseriös!“ aber Mr. Condon versteht die Not seiner Entwicklerkollegen und hat dies in seinem Plugin vorgesehen. Sie können seine Dokumentation zu diesem Thema einsehen, aber ich werde einige davon hier wiederholen. Gehen wir die Regeln durch.
- Erstens, wenn Sie ein kostenloses Plugin verteilen, müssen Sie die kostenlose Version von ACF verwenden. Das liegt daran, dass die Leute die PRO-Version Ihres kostenlosen Plugins nicht bekommen können – das wäre nicht cool. Sie können die PRO-Version problemlos in Premium-Plugins und -Designs verwenden, stellen Sie einfach sicher, dass Sie die Entwicklerlizenz kaufen.
- Zweitens: Verändern Sie nicht die Copyright-Informationen von ACF. Geben Sie dem Mann etwas Anerkennung!
- Schließlich verteilen Sie den Lizenzschlüssel nicht mit Ihrem Plugin.
Nun die Vor- und Nachteile dieses Ansatzes:
Vorteile
- Sehr einfach in Themes und Plugins zu integrieren
- Sie können die erweiterten Felder nutzen, die Teil von ACF sind
- Code- und Sicherheitsupdates werden vom ACF-Team verwaltet
- ACF hat großartige Addons und Unterstützung, wenn Sie nicht weiterkommen
- Das Konfigurieren Ihrer Felder ist aufgrund der Benutzeroberfläche für die Feldkonfiguration sehr einfach
Nachteile
- Eingeschränkter Zugriff auf Markups
- Erstellt eine Abhängigkeit für Ihr Plugin oder Design
- Um ACF auf dem neuesten Stand zu halten, müssen Sie es in Ihren Plugin-/Theme-Dateien auf dem neuesten Stand halten (weitere Informationen unten).
Wann sollten Sie diesen Ansatz verwenden?
Wenn Sie sehr schnell eine erweiterte Einstellungsschnittstelle erstellen möchten und das Erscheinungsbild nicht anpassen müssen.
Einstieg
For this approach I will show you how to set up the options page for the free version of ACF. To view a guide on setting up the PRO version check out the ACF documentation. To get started we will be adding ACF to our plugin directory. First, download the latest version of ACF and unzip its contents. In your plugin directory create a (Große Version anzeigen)
Again, we will follow the steps we did in “Creating Our Plugin And Settings Page”. Before we get into that, though, we should include ACF in our plugin.
Include ACF In Your Plugin
It's actually pretty easy to include ACF in your plugin – there are only three steps. First we have to include the main ACF file with PHP. Add the following code to the bottom of our constructor function:
include_once( plugin_dir_path( __FILE__ ) . 'vendor/advanced-custom-fields/acf.php' );
If you refresh the admin you should see a new menu item titled Custom Fields . Before we go into that page and start setting up our fields we need to update a couple of paths in ACF. We need to tell ACF to look for its front-end assets and file includes in our plugin directory instead of its normal place. Add these two hooks to your constructor:
add_filter( 'acf/settings/path', array( $this, 'update_acf_settings_path' ) ); add_filter( 'acf/settings/dir', array( $this, 'update_acf_settings_dir' ) );
And the callbacks for those hooks:
public function update_acf_settings_path( $path ) { $path = plugin_dir_path( __FILE__ ) . 'vendor/advanced-custom-fields/'; return $path; } public function update_acf_settings_dir( $dir ) { $dir = plugin_dir_url( __FILE__ ) . 'vendor/advanced-custom-fields/'; return $dir; }
The first callback updates the include paths for the PHP files within the ACF plugin. The second updates the URIs for the ACF assets. Now we can set up our fields.
Configuring Your Fields
Now comes the fun part: the ACF field configuration UI. Add a title and any fields you'd like in your form. There is a great walkthrough of what everything on this page does in the ACF documentation. Here's how I have set up mine:

Once you are ready hit the Publish button on the right and your fields will be saved. Now we have to get the fields we set up into our plugin. Right now they only exist in the database. On the left-hand navigation, click the Tools item. On the new page, select the field group we just created and hit Generate Export Code . This will create a chunk of PHP code that we can now include in our plugin.
To add the options, we need to add a method call to our constructor. Add this line to the end of your constructor after our ACF include:
$this->setup_options();
Then we can create the method that will wrap our options:
public function setup_options() { if( function_exists( 'register_field_group' ) ) { register_field_group(array ( 'id' => 'acf_awesome-options', 'title' => 'Awesome Options', 'fields' => array ( array ( 'key' => 'field_562dc35316a0f', 'label' => 'Awesome Name', 'name' => 'awesome_name', 'type' => 'text', 'default_value' => ', 'placeholder' => ', 'prepend' => ', 'append' => ', 'formatting' => 'html', 'maxlength' => ', ), array ( 'key' => 'field_562dc9affedd6', 'label' => 'Awesome Date', 'name' => 'awesome_date', 'type' => 'date_picker', 'date_format' => 'yymmdd', 'display_format' => 'dd/mm/yy', 'first_day' => 1, ), array ( 'key' => 'field_562dc9bffedd7', 'label' => 'Awesome WYSIWYG', 'name' => 'awesome_wysiwyg', 'type' => 'wysiwyg', 'default_value' => ', 'toolbar' => 'full', 'media_upload' => 'yes', ), ), 'location' => array ( array ( array ( 'param' => 'options_page', 'operator' => '==', 'value' => 'smashing_fields', ), ), ), 'menu_order' => 0, 'position' => 'normal', 'style' => 'default', 'label_placement' => 'top', 'instruction_placement' => 'label', 'hide_on_screen' => ', 'active' => 1, 'description' => ', )); } }
Now that we have our fields ready to go, we can add them to the settings page.
Modifying The Settings Page Code
To add the fields we just created to the page we will need to update our plugin_settings_page_content
method.
Previously, we set up the form tag for our page. In this case we will let ACF do that part for us. Here is what our updated function should look like:
public function plugin_settings_page_content() { do_action('acf/input/admin_head'); // Add ACF admin head hooks do_action('acf/input/admin_enqueue_scripts'); // Add ACF scripts $options = array( 'id' => 'acf-form', 'post_id' => 'options', 'new_post' => false, 'field_groups' => array( 'acf_awesome-options' ), 'return' => admin_url('admin.php?page=smashing_fields'), 'submit_value' => 'Update', ); acf_form( $options ); }
Die ersten beiden Zeilen unserer Funktion fügen die Skripte und Stile hinzu, die wir für die Einstellungsfelder benötigen. Danach konfigurieren wir die Optionen für unser Formular. Möglicherweise stellen Sie fest, dass der Wert im Argument field_groups
mit der ID aus unserer Funktion register_field_group
übereinstimmt. Um die anderen Konfigurationsparameter zu sehen, werfen Sie einen Blick in die acf_form
Dokumentation. Die letzte Zeile in unserer Funktion wird das Formular tatsächlich rendern.
Wenn Sie jetzt versuchen, die Einstellungsseite zu laden, sehen Sie möglicherweise, dass die Seite tatsächlich defekt ist. Dies liegt daran, dass ACF einige Variablen für JavaScript lokalisieren muss. Dazu müssen wir unserem Konstruktor einen weiteren Hook hinzufügen:
add_action( 'admin_init', array( $this, 'add_acf_variables' ) );
Jetzt müssen wir den Rückruf einrichten:
public function add_acf_variables() { acf_form_head(); }
Sie können versuchen, Inhalte hinzuzufügen und zu speichern, und es sollte genau wie unsere anderen beiden Ansätze funktionieren. So soll unsere Seite aussehen:

Es gibt nur ein paar Aufräumarbeiten, die wir ansprechen müssen:
Vielleicht möchten Sie die Tatsache verbergen, dass Sie ACF für Ihr Plugin verwenden. In diesem Fall müssen Sie den Menüpunkt Benutzerdefinierte Felder ausblenden. Sie können dies tun, indem Sie dieses Snippet zu Ihrer Konstruktorfunktion hinzufügen:
add_filter( 'acf/settings/show_admin', '__return_false' );
Wir sollten die Datenbankversion unserer Feldgruppe entfernen. Gehen Sie einfach zum Abschnitt „Benutzerdefinierte Felder“ und klicken Sie auf die Schaltfläche „Papierkorb“. Dieser Schritt ist optional, da er sich nur auf die Umgebung auswirkt, in der Sie das Plug-in erstellt haben, aber er könnte zu Problemen führen, wenn Sie Ihr Plug-in in derselben Umgebung testen.
Verwenden von ACF-Feldern in Ihrem Plugin
Um die von Ihnen erstellten ACF-Felder abzurufen, müssen Sie einfach die ACF-Standardfunktion get_field
verwenden. Die erste Option sollte die eindeutige ID für das Feld sein und das zweite Argument sollte auf 'option'
gesetzt sein. So erhalten wir das Feld „ Awesome Date “:
get_field( 'awesome_date', 'option' )
Und das ist es. Sie haben jetzt ein Plugin mit ACF-Einstellungen eingerichtet! Sie können den Code für diesen Ansatz im Repository anzeigen.
Fazit
Da haben Sie es also: drei Möglichkeiten, Ihre Plugins konfigurierbar zu machen. Ich würde gerne von den Plugins hören, die Sie mit diesen Methoden erstellen können. Auch hier habe ich ein Repository eingerichtet, das den Code für jeden dieser Ansätze enthält. Bitte zögern Sie nicht, sie zu forken und an Ihre eigenen Bedürfnisse anzupassen.
Was meine persönlichen Vorlieben für diese Ansätze betrifft, tendiere ich eher zu Ansatz 1. Ich ziehe es vor, so wenig Abhängigkeiten wie möglich in meinen Plugins zu behalten, und Sie können das Markup anpassen, um die Einstellungsseite für benutzerdefinierte Projekte zu gestalten. Für schnelle Prototypen oder Projekte, bei denen ich sehr fortgeschrittene Felder einrichten muss, werde ich ACF verwenden – aber es erhöht die Komplexität der Verwaltung von Plugin-Updates.
Erwähnenswert ist auch der Vorschlag für eine Fields API von Scott Clark. Während es derzeit noch in Arbeit ist, würde die API im Wesentlichen Plug-in- und Theme-Entwicklern die Möglichkeit geben, dieselbe Schnittstelle wie die Customizer-API zu verwenden, um Einstellungsfelder in anderen Bereichen des Admin-Panels zu erstellen.
ACF-Alternativen
Wie in den Kommentaren unten ausgeführt, und um Entwicklern andere Optionen zu geben, die dem ACF-Ansatz ähneln, können Sie sich einige Alternativen ansehen, die möglicherweise andere Funktionen bieten. Wenn Sie mehr haben, senden Sie sie bitte in den Kommentaren unten! Hier sind sie in keiner bestimmten Reihenfolge:
- CMB2 von WebDevStudios
- Meta Box von Tran Ngoc Tuan Anh ( Rilwis )