3 podejścia do dodawania konfigurowalnych pól do wtyczki WordPress

Opublikowany: 2022-03-10
Szybkie podsumowanie ↬ Każdy, kto stworzył wtyczkę WordPress, rozumie potrzebę tworzenia konfigurowalnych pól, aby zmodyfikować sposób działania wtyczki. Istnieje niezliczona ilość zastosowań konfigurowalnych opcji we wtyczce i prawie tyle samo sposobów ich implementacji. Widzisz, WordPress pozwala autorom wtyczek na tworzenie własnych znaczników na swoich stronach ustawień. Jako efekt uboczny, strony ustawień mogą się znacznie różnić między wtyczkami. W tym artykule omówimy trzy popularne sposoby konfiguracji wtyczki. Zaczniemy od utworzenia strony ustawień i stworzenia naszych pól przy użyciu domyślnego interfejsu API ustawień WordPress. Następnie przeprowadzę Cię przez proces konfigurowania pól za pomocą niestandardowego modułu obsługi. Na koniec pokażę, jak zintegrować świetną konfigurowalną wtyczkę Fields Advanced Custom Fields (ACF) we własnej wtyczce.

Każdy, kto stworzył wtyczkę WordPress, rozumie potrzebę tworzenia konfigurowalnych pól, aby zmodyfikować sposób działania wtyczki. Istnieje niezliczona ilość zastosowań konfigurowalnych opcji we wtyczce i prawie tyle samo sposobów ich implementacji. Widzisz, WordPress pozwala autorom wtyczek na tworzenie własnych znaczników na swoich stronach ustawień. Jako efekt uboczny, strony ustawień mogą się znacznie różnić między wtyczkami.

W tym artykule omówimy trzy popularne sposoby konfiguracji wtyczki. Zaczniemy od utworzenia strony ustawień i stworzenia naszych pól przy użyciu domyślnego interfejsu API ustawień WordPress.

Dalsze czytanie na SmashingMag:

  • Rozszerz WordPressa o niestandardowe pola
  • Niestandardowe hacki pól dla WordPress
  • Rozszerzanie zaawansowanych niestandardowych pól za pomocą własnych elementów sterujących
  • Kompletny przewodnik po niestandardowych typach postów

Następnie przeprowadzę Cię przez proces konfigurowania pól za pomocą niestandardowego modułu obsługi. Na koniec pokażę, jak zintegrować świetną konfigurowalną wtyczkę Fields Advanced Custom Fields (ACF) we własnej wtyczce.

Więcej po skoku! Kontynuuj czytanie poniżej ↓

Ponieważ jest to długi post, oto spis treści z linkami do każdej z głównych sekcji:

  • Tworzenie naszej wtyczki i strony ustawień
  • Podejście 1: Korzystanie z wbudowanej funkcjonalności WordPress
  • Podejście 2: Konfiguracja niestandardowego formularza i obsługi
  • Podejście 3: integracja ACF (zaawansowanych pól niestandardowych) z wtyczką

Aby zapoznać się z przykładami kodu, zobacz repozytorium, które stworzyłem, aby towarzyszyć temu poście.

Tworzenie naszej wtyczki i strony ustawień

Pierwszą rzeczą, którą musimy zrobić, to skonfigurować naszą wtyczkę i utworzyć stronę ustawień. Wszystkie trzy podejścia opisane w tym artykule zaczynają się od poniższej struktury wtyczki. Ta struktura wtyczki jest zorientowana obiektowo , więc może wystąpić kilka różnic w twoim kodzie, jeśli twoja wtyczka jest napisana proceduralnie. Zwróć szczególną uwagę na format funkcji zwrotnej w akcjach i filtrach.

 /* 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();

Wewnątrz naszej klasy dodamy hak akcji, aby dodać stronę ustawień:

 public function __construct() { // Hook into the admin menu add_action( 'admin_menu', array( $this, 'create_plugin_settings_page' ) ); }

Widać, że callback naszej akcji to create_plugin_settings_page , więc stwórzmy tę metodę. Uwaga: Ustawiłem argumenty jako oddzielne nazwane zmienne, aby nadać kontekst naszemu kodowi, ale możesz po prostu umieścić wartości bezpośrednio w funkcji, aby zaoszczędzić pamięć.

 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 ); }

Zapoznaj się z kodeksem WP dla add_menu_page , aby uzyskać więcej informacji.

Ta funkcja utworzy naszą stronę, a także pozycję menu. Ważnymi częściami są tutaj argumenty slug, możliwości i wywołania zwrotnego. Ślimak, którego użyjemy później do zarejestrowania naszych pól, więc gdzieś to zapisz. Możesz zmienić tę możliwość, aby zezwolić różnym poziomom użytkowników na dostęp do strony ustawień. Jeśli chodzi o wywołanie zwrotne, wkrótce stworzymy tę metodę. Zauważ, że możesz również umieścić klasę dashicon bezpośrednio w funkcji, aby zmienić ikonę menu. Ostatnim argumentem jest pozycja pozycji menu w menu; baw się z tym numerem, aby znaleźć miejsce w menu, w którym chcesz, aby Twoje ustawienia spadły. Uwaga: możesz użyć wartości dziesiętnych, aby uniknąć konfliktów z innymi pozycjami menu.

Naszym następnym krokiem jest utworzenie metody wywołania zwrotnego plugin_settings_page_content dla naszej strony ustawień.

 public function plugin_settings_page_content() { echo 'Hello World!'; }

Jeśli zapiszesz wtyczkę i odświeżysz panel administracyjny WordPressa, powinieneś zobaczyć następujące informacje:

Układ początkowy dla strony ustawień
Stan początkowy strony ustawień. (Wyświetl dużą wersję)

Widać, że strona ustawień jest elementem menu najwyższego poziomu. Możesz zostawić to w ten sposób, w zależności od potrzeb Twojej strony ustawień. Jednak możesz również chcieć, aby ustawienia wtyczki znajdowały się w innej pozycji menu. W takim przypadku po prostu zmienisz ostatnią linię metody create_plugin_settings_page na następującą:

 add_submenu_page( 'options-general.php', $page_title, $menu_title, $capability, $slug, $callback );

Tutaj zmieniamy funkcję add_menu_page na add_submenu_page i dodajemy nowy argument. Ten argument jest nadrzędnym elementem menu, pod którym będzie znajdować się nowa strona ustawień. W dokumentacji add_submenu_page możesz zobaczyć całkiem niezłą listę pozycji menu nadrzędnego i ich slugów. Możesz również zauważyć, że nie mamy już dwóch ostatnich argumentów, $icon i $position . Ponieważ jesteśmy teraz w sekcji podmenu, nie mamy już kontroli nad położeniem elementu. Ponadto podmenu nie mają dostępnych ikon, więc nie ma potrzeby podawania tego argumentu.

Jeśli zapiszesz ten nowy kod, zobaczysz, że nasza strona ustawień zostanie wyświetlona w pozycji menu Ustawienia:

Strona podmenu jest teraz w ustawieniach
Strona ustawień została teraz umieszczona w menu Ustawienia. (Wyświetl dużą wersję)

W wielu przypadkach najbardziej odpowiednim miejscem do dodania strony z ustawieniami wtyczki jest pozycja Ustawienia. W kodeksie WordPress wyjaśnia, że ​​sekcja Ustawienia służy do „Wyświetlania opcji wtyczek, które powinni przeglądać tylko administratorzy”. To jednak tylko wskazówka, a nie reguła.

Teraz, gdy mamy skonfigurowaną stronę ustawień i wiemy, jak przenosić elementy, możemy rozpocząć pracę nad polami. Praca, którą wykonaliśmy do tej pory, zostanie ponownie wykorzystana w różnych poniższych metodach.

Podejście 1: Korzystanie z wbudowanej funkcjonalności WordPress

Zanim zagłębimy się w kod, przyjrzyjmy się niektórym zaletom i wadom takiego podejścia.

Plusy

  • Łatwa integracja z istniejącymi stronami ustawień
  • Odkażanie jest wykonywane za Ciebie
  • Mało prawdopodobne, aby się zepsuł, ponieważ kod jest zarządzany przez WordPress
  • Może być używany zarówno do motywów, jak i wtyczek
  • Elastyczny, bezpieczny i rozszerzalny

Cons

  • Weryfikacja danych niestandardowych jest ręczna
  • Zaawansowane typy pól (repeatery, mapy, przesyłanie itp.) są trudniejsze do wdrożenia

Kiedy powinieneś skorzystać z tego podejścia?

Takie podejście jest na tyle elastyczne, że można je dostosować do bardzo prostych lub bardzo zaawansowanych stron ustawień. Możesz użyć tej metody w większości sytuacji, jeśli nie masz nic przeciwko robieniu niektórych rzeczy ręcznie.

Pierwsze kroki

Korzystając z tego podejścia, będziemy musieli zastosować te same znaczniki, których używają strony opcji WordPress. Powinniśmy zmodyfikować naszą metodę plugin_settings_page_content w następujący sposób:

 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 }

Powyższy znacznik pochodzi bezpośrednio z kodeksu WordPress na temat tworzenia stron opcji. Nazwa metody powinna być zgodna z nazwą wywołania zwrotnego, którą umieściliśmy w funkcji add_menu_page powyżej. Wrapper div jest w rzeczywistości taki sam jak domyślny formularz WordPress i pobiera style z tych sekcji. Znacznik form wskazuje na domyślny program obsługi formularzy opcji dla WordPress.

Trzy linie PHP robią kilka rzeczy:

  • Funkcja settings_fields jest w zasadzie odniesieniem do pozostałych naszych pól. Argument ciągu znaków, który umieścisz w tej funkcji, powinien pasować do zmiennej $slug , którą ustawiliśmy wcześniej – będzie on znajdował się we wszystkich polach, które zarejestrujemy później we wtyczce. Ta funkcja wyświetla również kilka ukrytych danych wejściowych dla jednorazowych, akcji formularza i kilku innych pól na stronie opcji.
  • Następna funkcja, do_settings_sections , jest symbolem zastępczym dla sekcji i pól, które zarejestrujemy w innym miejscu w naszej wtyczce.
  • Ostatnia funkcja, submit_button , wygeneruje dane wejściowe, ale doda również kilka klas na podstawie stanu strony. Mogą istnieć inne argumenty, które będziesz chciał przekazać do funkcji submit_button ; są one opisane w kodeksie.

Jeśli odświeżymy naszą stronę ustawień, powinniśmy otrzymać coś takiego:

Pusta strona ustawień WordPress
Nasza strona ustawień przed zarejestrowaniem sekcji i pól.

Wygląda trochę skromnie! Zacznijmy teraz konfigurować pola.

Sekcje i pola

WordPress dzieli swoje strony opcji na sekcje. Każda sekcja może mieć powiązaną z nią listę pól. Musimy zarejestrować sekcję w naszej wtyczce, zanim zaczniemy dodawać nasze pola. Dodaj następujący kod do funkcji konstruktora:

 add_action( 'admin_init', array( $this, 'setup_sections' ) );

Ten haczyk utworzy sekcje na naszej stronie. Oto kod wywołania zwrotnego:

 public function setup_sections() { add_settings_section( 'our_first_section', 'My First Section Title', false, 'smashing_fields' ); }

Pierwszy argument jest unikalnym identyfikatorem sekcji i będziemy go używać dla pól, które chcemy przypisać do sekcji. Te identyfikatory powinny być unikalne dla wszystkich nowych sekcji na tej stronie. Kolejnym argumentem jest tytuł, który jest generowany nad sekcją – możesz zrobić to, co chcesz. Trzeci argument to callback. W tej chwili mam to ustawione na false , ale wkrótce do tego wrócimy. Czwartym argumentem jest strona opcji, do której zostaną dodane opcje (wcześniej zmienna $slug ).

Dlaczego więc w naszym callbacku jest false ? Cóż, coś, co nie jest jasne podczas konfigurowania opcji WordPress przy użyciu ich dokumentacji, to fakt, że wiele sekcji może udostępniać wywołanie zwrotne. Często podczas konfigurowania wywołania zwrotnego istnieje relacja 1 do 1 między podpięciem a wywołaniem zwrotnym. Na przykład spróbujmy utworzyć trzy sekcje z tym samym wywołaniem zwrotnym:

 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' ); }

Wszystkie trzy z tych sekcji mają wywołanie zwrotne section_callback ustawione w tym trzecim slocie argumentów. Jeśli następnie utworzymy metodę, która pasuje do tego wywołania zwrotnego i umieścimy tam „Hello World”:

 public function section_callback( $arguments ) { echo '

Witaj świecie

'; }

otrzymujemy coś, co wygląda tak:

Trzy sekcje dzielą tę samą funkcję zwrotną
Trzy sekcje dzielące to samo wywołanie zwrotne.

Wiem, co myślisz: „Dlaczego do cholery miałbym chcieć mieć ten sam tekst we wszystkich moich sekcjach?” Odpowiedź brzmi, że prawdopodobnie nie. W tym miejscu możemy się trochę skomplikować z funkcją add_settings_section . Jeśli spojrzysz na dokumentację tej funkcji, zobaczysz, że w części strony z uwagami do funkcji zwrotnej zostanie przypisana tablica argumentów, które bezpośrednio korelują z argumentami w naszym przechwyceniu. Jeśli wejdziesz i var_dump( $arguments ) , zobaczysz wszystkie argumenty przekazywane do naszej funkcji.

Następnie możemy napisać prosty przełącznik w naszym wywołaniu zwrotnym, aby zmienić tekst na podstawie przekazanego do niego identyfikatora:

 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; } }

Teraz mamy niestandardowy tekst dla każdej sekcji, który możemy zmienić w jednej funkcji!

Niestandardowy tekst pod każdą sekcją
Niestandardowy tekst pod każdą sekcją.

Oczywiście możesz również określić unikalne wywołania zwrotne dla tych sekcji, ale takie podejście pozwala skonsolidować kod w jedną funkcję. Ten pomysł działa tak samo w przypadku konfigurowania pól. Możemy sprawić, by wszystkie nasze pola współdzieliły wywołanie zwrotne i wygenerowały właściwy typ pola na podstawie przekazanych przez nas argumentów. Dodajmy pola do naszej metody konstruktora. Umieść ten kod zaraz po zaczepie naszych sekcji w konstruktorze:

 add_action( 'admin_init', array( $this, 'setup_fields' ) );

Ponieważ znasz już ćwiczenie, podam ci tylko oddzwonienie do naszego działania:

 public function setup_fields() { add_settings_field( 'our_first_field', 'Field Name', array( $this, 'field_callback' ), 'smashing_fields', 'our_first_section' ); }

Argumenty w tej funkcji są podobne do tych w funkcji section. Pierwszy argument to unikalny identyfikator pola. Druga to etykieta, która pojawia się obok pola. W trzecim argumencie widać, że wywołuję metodę field_callback ; stworzymy to wywołanie zwrotne w ciągu sekundy. Czwarta to strona opcji, której chcemy użyć (nasz $slug z wcześniejszej wersji). Piątym argumentem jest unikalny identyfikator sekcji , do której chcemy przypisać to pole.

Oto kod wywołania zwrotnego w naszym trzecim argumencie:

 public function field_callback( $arguments ) { echo '<input name="our_first_field" type="text" value="' . get_option( 'our_first_field' ) . '" />'; }

Tutaj po prostu kopiuję unikalny identyfikator pola do nazwy, identyfikatora i naszej funkcji get_option . Zobaczmy jak wygląda nasza strona z dołączonym nowym polem:

Nasza strona ustawień z naszym pierwszym polem.
Strona ustawień z załączonym pierwszym polem.

Super, mamy swoje pole na stronie! Spróbuj dodać do niego trochę treści i naciśnij Zapisz zmiany, poczekam tutaj…

Czy ty to zrobiłeś? Jeśli zrobiłeś wszystko do tego momentu, powinieneś otrzymać błąd mówiący coś w rodzaju ERROR: options page not found lub podobny. Powodem, dla którego tak się dzieje, jest w rzeczywistości funkcja bezpieczeństwa w WordPress.

Widzisz, bez tej funkcji użytkownik mógłby przejść do HTML i zmienić nazwę pola na dowolną, jaką chciał, nacisnąć przycisk Zapisz, a on wpisałby tę opcję do bazy danych pod jakąkolwiek nazwą, którą nadał (zakładając, że była to prawidłowa nazwa opcji). Może to pozwolić każdemu użytkownikowi na zmianę opcji na innych stronach (nawet tych, do których normalnie nie miał dostępu), po prostu wpisując poprawną nazwę w polu i naciskając Zapisz – nie jest fajne.

Ten problem został rozwiązany przez dodanie funkcji o nazwie register_setting . O ile wyraźnie nie powiesz WordPressowi „Hej, to pole może być zapisane na tej stronie”, WordPress nie zaktualizuje pola w bazie danych. Tak więc pod naszym znacznikiem pola dodamy tę nową funkcję. Oto jak wygląda callback po dodaniu kodu:

 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' ); }

Pierwszym argumentem w nowej funkcji jest strona opcji, na której chcemy zapisać pole (wcześniej $slug ), a drugim argumentem jest pole, które chcemy zapisać. Teraz spróbuj zaktualizować pole – zadziałało!

Gratulacje! Właśnie zapisałeś swoje pierwsze pole za pomocą interfejsu API ustawień WordPress. A co, jeśli chcemy mieć różne typy pól zamiast samego tekstu? Wróćmy do naszego wywołania zwrotnego pola i porozmawiajmy o przekazywaniu zmiennej $arguments do naszej funkcji.

Argumenty terenowe

Jeśli przejdziemy do naszego pola callback i var_dump( $arguments ) , otrzymamy pustą tablicę. Co daje? W naszym wywołaniu zwrotnym sekcji otrzymaliśmy sporo informacji o sekcji. Cóż, dzieje się tu coś innego. Jeśli zajrzysz do dokumentacji dla add_settings_field , istnieje piąty argument, który można przekazać do funkcji. Ta zmienna jest bezpośrednio skorelowana ze zmienną $arguments w naszym wywołaniu zwrotnym. Więc będziemy chcieli tam umieścić nasze nowe rzeczy.

Jeśli spojrzymy na jedno z domyślnych pól na stronie ustawień WordPress, zobaczymy, że istnieje kilka obszarów, które możemy dodać do naszego pola, aby uzyskać domyślne formatowanie. Oto zrzut ekranu pola strefy czasowej na stronie ustawień ogólnych:

Pole strefy czasowej WordPress
Pole strefy czasowej WordPress. (Wyświetl dużą wersję)

Używając tego pola jako punktu wyjścia, przejrzyjmy dane, które chcemy przekazać do naszego pola wywołania zwrotnego.

  • Unikalny identyfikator
  • Etykieta pola (w przykładzie strefa czasowa)
  • Do jakiej sekcji powinno się przejść
  • Typ pola (tekst, pole tekstowe, zaznaczenie itp.)
  • W przypadku, gdy istnieje wiele opcji, będziemy ich potrzebować
  • Może symbol zastępczy, jeśli typ pola go obsługuje
  • Tekst pomocniczy (po prawej stronie pola w przykładzie)
  • Tekst uzupełniający (pod polem w przykładzie)
  • Może wybór domyślny, jeśli taki istnieje

Z tej listy możemy skonfigurować asocjacyjną tablicę pól i wartości, które możemy przekazać do naszego wywołania zwrotnego:

 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'] ); } }

Pierwszą rzeczą, jaką mamy tutaj, jest zmienna o nazwie $fields , która będzie zawierać wszystkie pola, które chcemy utworzyć. Wewnątrz tej tablicy mamy inną tablicę, która przechowuje określone dane dla każdego pola. Skonfigurowałem dane tak, aby dokładnie odpowiadały naszej powyższej liście. Następnie przechodzę przez każde pole (wkrótce dodamy więcej) w tablicy, dodaję pole i rejestruję je. Na końcu funkcji add_settings_field również całą tablicę danych dla tego konkretnego pola, abyśmy mogli zrobić kilka rzeczy w funkcji zwrotnej. Rzućmy okiem na tę funkcję zwrotną tutaj:

 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 } }

W powyższym przykładzie robimy kilka rzeczy. Ustawiamy wartości domyślne dla pól, jeśli są puste i dodajemy tekst pomocniczy i uzupełniający. Jednak najważniejszą częścią naszego kodu jest instrukcja switch. W tym oświadczeniu zamierzamy nakreślić, w jaki sposób nasze argumenty będą obsługiwane w oparciu o żądany typ pola.

Na przykład, jeśli mamy pole tekstowe, nie musimy mieć wielu opcji. Jednak menu rozwijane <select> musi zawierać opcje, aby działać poprawnie. Ponieważ mamy już skonfigurowane typy tekstu, uruchommy ten kod i zobaczmy, co otrzymamy.

Nasze pole wypełnione wraz z symbolem zastępczym
Nasze pole wypełnione wraz z tekstem zastępczym. (Wyświetl dużą wersję)

Po załadowaniu strony ustawień wtyczki powinieneś zobaczyć górne pole na tym obrazie. Dół jest tym, co zobaczysz, jeśli usuniesz zawartość z pola (tj. symbol zastępczy). Gdybym miał supplimental argumenty helper lub dodatkowe z naszej tablicy pól, powinny zniknąć na stronie ustawień. Możemy również zmienić argument section i poruszać się po rozmieszczeniu pola w sekcjach.

OK, więc mamy pola tekstowe; co powiesz na bardziej złożone typy pól? Przyjrzyjmy się jeszcze raz naszej instrukcji switch i dodajmy opcję dla obszarów tekstowych i pojedynczych wyborów:

 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; }

W powyższym kodzie zauważysz kilka różnic między każdym z typów pól. Chociaż obszary tekstowe są funkcjonalnie podobne do zwykłych pól tekstowych, wymagają innych znaczników. Wybierz listy rozwijane to zupełnie inne zwierzę ze względu na opcje. Musimy przejrzeć opcje i ustawić wartości, wybrane stany i etykiety. Więc nasz znacznik jest drastycznie inny.

Teraz, gdy zaktualizowaliśmy naszą funkcję zwrotną, zobaczmy, jak zmieniły się dane pola:

 $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' ) );

Oto trzy pola, z których każde wykorzystuje inny typ pola w naszej wtyczce. Pierwszy, który już przeszliśmy. Drugie to nasze nowe pole textarea . Możemy przekazać te same parametry z tablicą (z wyjątkiem UID), ale prosta zmiana naszego typu i zamiast tego otrzymamy textarea . Ostatnie pole w tej tablicy to lista rozwijana wyboru. Główną aktualizacją jest dodanie tablicy opcji. Dodajemy prostą tablicę asocjacyjną z kluczem tablicy jako wartością opcji HTML i etykietą. Korzystając z tej tablicy, oto jak wyglądają nasze pola:

Nasza strona ustawień po wypełnieniu pól
Nasza strona ustawień z polami. (Wyświetl dużą wersję)

Prawie skończone!

Mamy teraz działającą stronę ustawień wtyczki. Skonfigurowaliśmy sekcje dla strony, opcje, wszystkie wywołania zwrotne i zarejestrowaliśmy pola. Jedyne, co pozostało, to uzyskanie naszych wartości ustawień w innym miejscu. Wierz lub nie, już to zrobiliśmy. Na górze naszego pola callback możesz zobaczyć, że sprawdzamy wartość bazy danych:

 $value = get_option( $arguments['uid'] );

Możemy użyć tego samego kodu w naszej wtyczce (lub motywie) i po prostu przekazać uid do funkcji. Więc gdybym chciał uzyskać wartość our_first_field , napisałbym po prostu:

 get_option('our_first_field')

Cześć Presto! Mamy naszą niesamowitą wtyczkę i nasze niesamowite ustawienia! Oczywiście ustawiliśmy tylko kilka typów pól, ale przejrzałem i dodałem więcej w repozytorium kodu dla tego podejścia (w szczególności pola tekstowe, hasła, liczby, obszary tekstowe, listy rozwijane wyboru, opcje wielokrotnego wyboru, przyciski radiowe i pola wyboru).

Podejście 2: Konfigurowanie niestandardowego formularza i obsługi

W przeszłości takie podejście było jedynym sposobem dodawania stron ustawień. Przed WordPress 2.7 autorzy wtyczek musieli tworzyć własne niestandardowe formularze i programy obsługi. To oczywiście doprowadziło do wielu błędów i niespójności między wtyczkami. Chociaż to podejście jest nieco przestarzałe, w niektórych przypadkach nadal jest realną opcją.

Plusy

  • Możesz przesłać formularz do obsługi niestandardowej i zdalnej
  • Możesz ominąć niektóre z wbudowanych ograniczeń interfejsu Settings API

Cons

  • Deweloper musi zachować kompatybilność
  • Należy odkazić i zweryfikować ręcznie

Kiedy powinieneś skorzystać z tego podejścia?

Użyj tego podejścia, gdy absolutnie musisz mieć niestandardowy program obsługi lub wysoce niestandardowy interfejs. Prawdopodobnie w większości przypadków możesz ujść na sucho z podejściem 1, ale masz większą elastyczność w zakresie walidacji i obsługi przy użyciu tej metody.

Pierwsze kroki

Zanim przejdziemy do szczegółów, musimy wymyślić scenariusz, w którym użyjemy niestandardowego modułu obsługi. Dla uproszczenia stwórzmy formularz, który zweryfikuje nazwę użytkownika i adres e-mail. Moglibyśmy pobrać dane z bazy danych lub nawet ze zdalnego serwera. W takim przypadku skonfiguruję tablicę z prawidłowymi nazwami użytkowników i adresami e-mail do sprawdzenia. Następnie będziemy przechowywać wartości pól wprowadzone przez użytkownika i przechowywać je w bazie danych.

Tworzenie formularza

Jak wspomniałem wcześniej, wykonamy te same kroki, które zrobiliśmy w „Tworzeniu naszej strony wtyczki i ustawień”. W tym podejściu skonfigurujemy nasze pola za pomocą statycznego znacznika HTML. Dodamy ten kod do wywołania zwrotnego z funkcji plugin_settings_page_content w następujący sposób:

 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 }

Jak widać powyżej, po prostu dodajemy statyczny kod HTML dla naszych pól. Powielamy znaczniki z podstawowych stron ustawień WordPressa. Pomijamy również akcję formularza, aby wysłał formularz do bieżącej strony, w przeciwieństwie do domyślnego modułu obsługi options.php .

Zanim napiszemy nasz niestandardowy program obsługi, dodajmy kilka szybkich funkcji bezpieczeństwa. Pierwszą rzeczą, którą powinniśmy zrobić, to umieścić w naszej formie jednorazówkę. Nonces chroni przed próbami fałszowania żądań między witrynami, co jest podobne do ataków podszywania się pod użytkownika lub powtórek. Umieśćmy jednorazowy numer w naszym kodzie HTML:

 <form method="POST"> <?php wp_nonce_field( 'awesome_update', 'awesome_form' ); ?> <table class="form-table">

Pole wp_nonce_field doda kilka ukrytych pól do naszego formularza; jednorazowy i odsyłający. Wrócimy do jednorazowości, gdy przejdziemy przez kod obsługi.

Następnie musimy dodać pole, aby wykryć, kiedy formularz został zaktualizowany. Możemy to zrobić, po prostu dodając ukryte pole u góry naszego formularza:

 <form method="POST"> <input type="hidden" name="updated" value="true" /> <?php wp_nonce_field( 'awesome_update', 'awesome_form' ); ?> <table class="form-table">

Teraz możemy umieścić fragment kodu na górze naszej strony, aby wykryć, kiedy nasz formularz został przesłany i wysłać nas do naszego niestandardowego modułu obsługi:

 public function plugin_settings_page_content() { if( $_POST['updated'] === 'true' ){ $this->handle_form(); } ?> <div class="wrap"> <h2>My Awesome Settings Page</h2>

Tutaj po prostu sprawdzamy, czy ukryte updated pole zostało przesłane, a jeśli tak, wywołujemy w naszej wtyczce metodę o nazwie handle_form . W tym miejscu możemy zacząć pisać nasz niestandardowy program obsługi.

Tworzenie obsługi

Jest kilka rzeczy, które musimy sprawdzić w module obsługi, zanim faktycznie zaczniemy zarządzać danymi formularza. Najpierw musimy sprawdzić, czy nasz nonce istnieje i jest ważny:

 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 } }

Powyższy kod weryfikuje, czy wartość jednorazowa jest poprawna. Jeśli jest nieprawidłowy, poinformujemy użytkownika, dlaczego formularz nie został zaktualizowany. Jeśli nonce istnieje i jest poprawne, możemy obsłużyć nasz formularz. Napiszmy teraz kod naszego modułu obsługi formularzy (ten kod zastąpi komentarz w powyższym fragmencie):

 $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 }

Przejdźmy przez kod w tej sekcji. Pierwsze kilka wierszy to tablice prawidłowych nazw użytkowników/adresów e-mail, z którymi będziemy sprawdzać. Te wartości tablicowe mogą być wypełniane z dowolnego miejsca.

Kolejne dwie linie to wartości, które wpisał w formularzu nasz użytkownik. Korzystamy z wbudowanych funkcji odkażania, które zapewnia nam WordPress. Ten krok jest ważny, aby uniknąć kilku luk w zabezpieczeniach formularzy internetowych. Następnie sprawdzamy, czy wartości podane przez użytkowników znajdują się w naszej tablicy wartości akceptowalnych. Jeśli tak, zaktualizuj opcje formularza w bazie danych. Ten krok można również zastąpić niestandardowym mechanizmem przechowywania. Przekazujemy również użytkownikowi komunikat, że jego pola zostały zapisane. Jeśli dane wprowadzone przez użytkownika są nieprawidłowe, informujemy o tym.

Ostatnią rzeczą, którą musimy zrobić, to pokazać zapisane pola w formularzu po ich wprowadzeniu. Zrobimy to w ten sam sposób, w jaki pobieramy te pola w innym miejscu wtyczki: za pomocą funkcji get_option . Oto pola po dodaniu poprawnego kodu:

 <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>

Teraz jesteśmy gotowi do przetestowania naszej formy. Spróbuj wpisać nazwę użytkownika admin i adres e-mail [email protected] . W swoim formularzu powinieneś otrzymać następujące informacje:

Zapisane pola po wpisaniu poprawnych wartości
Zapisane pola po wpisaniu prawidłowych wartości. (Wyświetl dużą wersję)

Jeśli spróbujesz ustawić w którymkolwiek polu nieprawidłową wartość, powinieneś otrzymać komunikat o błędzie, a pola nie powinny być aktualizowane z powodu naszego niestandardowego modułu obsługi.

To tyle, jeśli chodzi o nasze drugie podejście! Skonfigurowałeś teraz niestandardowy formularz i procedurę obsługi do zarządzania polami wtyczek. Ukończony kod dla tego podejścia można znaleźć w repozytorium tego artykułu. Przejdźmy teraz do naszego ostatecznego podejścia.

Podejście 3: integracja ACF (zaawansowanych pól niestandardowych) z wtyczką

Jeśli jeszcze nie używałeś ACF Elliota Condona, pozwól, że cię przedstawię. ACF to wspaniały menadżer terenowy dla WordPressa. Jedną z najlepszych rzeczy jest interfejs konfiguracji pola. Ułatwia tworzenie pól dla wielu różnych stron w WordPressie (takich jak posty, strony, użytkownicy, taksonomie, a nawet ich własne zintegrowane strony opcji). Możesz pomyśleć: „Nie mogę zintegrować cudzej wtyczki ze swoją własną – to podejrzane!” ale pan Condon rozumie trudną sytuację swoich kolegów programistów i zaplanował to w swojej wtyczce. Możesz zapoznać się z jego dokumentacją na ten temat, ale część z nich przedstawię tutaj. Przejdźmy przez zasady.

  1. Po pierwsze, jeśli dystrybuujesz darmową wtyczkę, musisz użyć darmowej wersji ACF. Dzieje się tak, aby ludzie nie mogli uzyskać wersji PRO z darmowej wtyczki – to nie byłoby fajne. Możesz bez problemu korzystać z wersji PRO we wtyczkach i motywach premium, po prostu upewnij się, że kupiłeś licencję programisty.
  2. Po drugie, nie zmieniaj informacji o prawach autorskich ACF. Daj mu trochę kredytu!
  3. Wreszcie, nie rozpowszechniaj klucza licencyjnego z wtyczką.

Teraz plusy i minusy tego podejścia:

Plusy

  • Bardzo łatwa integracja z motywami i wtyczkami
  • Możesz skorzystać z zaawansowanych pól, które są częścią ACF
  • Aktualizacje kodu i zabezpieczeń są zarządzane przez zespół ACF
  • ACF ma świetne dodatki i wsparcie, jeśli utkniesz
  • Konfiguracja pól jest bardzo prosta dzięki interfejsowi konfiguracji pól

Cons

  • Ograniczony dostęp do znaczników
  • Tworzy zależność dla Twojej wtyczki lub motywu
  • Aby ACF był aktualny, musisz aktualizować go w plikach wtyczek/motywów (więcej informacji poniżej)

Kiedy powinieneś skorzystać z tego podejścia?

Gdy chcesz bardzo szybko zbudować zaawansowany interfejs ustawień i nie musisz dostosowywać wyglądu i stylu.

Pierwsze kroki

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 (Wyświetl dużą wersję)

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:

ACF fields configured
My ACF fields in the configuration UI. (Wyświetl dużą wersję)

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 ); }

Pierwsze dwie linie naszej funkcji dodają skrypty i style, których będziemy potrzebować dla pól ustawień. Następnie konfigurujemy opcje dla naszego formularza. Możesz zauważyć, że wartość w argumencie field_groups odpowiada identyfikatorowi z naszej funkcji register_field_group . Aby zobaczyć inne parametry konfiguracyjne, zapoznaj się z dokumentacją acf_form . Ostatni wiersz w naszej funkcji w rzeczywistości wyrenderuje formularz.

Jeśli spróbujesz teraz załadować stronę ustawień, możesz zobaczyć, że strona jest rzeczywiście uszkodzona. Dzieje się tak, ponieważ ACF musi zlokalizować kilka zmiennych dla JavaScript. Aby to zrobić, musimy dodać kolejny hook do naszego konstruktora:

 add_action( 'admin_init', array( $this, 'add_acf_variables' ) );

Teraz musimy ustawić wywołanie zwrotne:

 public function add_acf_variables() { acf_form_head(); }

Możesz spróbować dodać trochę treści i zapisać i powinno działać tak samo, jak nasze pozostałe dwa podejścia. Tak powinna wyglądać nasza strona:

Gotowy formularz ACF
Nasz wypełniony formularz ACF. (Wyświetl dużą wersję)

Jest tylko kilka elementów porządkowych, którymi musimy się zająć:

  • Możesz ukryć fakt, że używasz ACF dla swojej wtyczki. W takim przypadku należy ukryć element menu Pola niestandardowe . Możesz to zrobić, dodając ten fragment kodu do funkcji konstruktora:

     add_filter( 'acf/settings/show_admin', '__return_false' );
  • Powinniśmy usunąć wersję bazy danych naszej grupy pól. Po prostu przejdź do sekcji pól niestandardowych i naciśnij przycisk kosza. Ten krok jest opcjonalny, ponieważ wpłynie tylko na środowisko, w którym zbudowałeś wtyczkę, ale może spowodować problemy, jeśli testujesz wtyczkę w tym samym środowisku.

Używanie pól ACF w Twojej wtyczce

Aby uzyskać utworzone pola ACF, wystarczy użyć domyślnej funkcji ACF get_field . Pierwsza opcja powinna być unikalnym identyfikatorem pola, a drugim argumentem ustawionym na 'option' . Oto jak otrzymalibyśmy pole Awesome Date :

 get_field( 'awesome_date', 'option' )

I to wszystko. Skonfigurowałeś wtyczkę z ustawieniami ACF! Możesz wyświetlić kod tego podejścia w repozytorium.

Wniosek

A więc masz to: trzy sposoby na skonfigurowanie wtyczek. Chciałbym usłyszeć o wtyczkach, które możesz stworzyć przy użyciu tych metod. Po raz kolejny stworzyłem repozytorium, w którym znajduje się kod dla każdego z tych podejść. Możesz je rozwidlić i dostosować do własnych potrzeb.

Jeśli chodzi o moje osobiste preferencje dotyczące tych podejść, skłaniam się ku Podejściu 1. Wolę zachować jak najmniej zależności w moich wtyczkach i możesz dostosować znaczniki, aby motywować stronę ustawień dla niestandardowych projektów. W przypadku szybkich prototypów lub projektów, w których muszę ustawić bardzo zaawansowane pola, użyję ACF – ale zwiększa to poziom złożoności w zarządzaniu aktualizacjami wtyczek.

Warto również wspomnieć o propozycji API Fields autorstwa Scotta Clarka. Chociaż obecnie nadal trwają prace, interfejs API zasadniczo umożliwiłby twórcom wtyczek i motywów korzystanie z tego samego interfejsu, co interfejs API Customizer, do tworzenia pól ustawień w innych obszarach panelu administracyjnego.

Alternatywy ACF

Jak wskazano w komentarzach poniżej, i aby dać programistom inne opcje, które są podobne do podejścia ACF, możesz sprawdzić kilka alternatyw, które mogą oferować różne funkcje. Jeśli masz więcej, prześlij je w komentarzach poniżej! Tutaj nie są one w określonej kolejności:

  • CMB2 autorstwa WebDevStudios
  • Meta Box autorstwa Tran Ngoc Tuan Anh (Rilwis)