向 WordPress 插件添加可配置字段的 3 種方法
已發表: 2022-03-10任何創建過 WordPress 插件的人都知道需要創建可配置字段來修改插件的工作方式。 插件中的可配置選項有無數種用途,實現上述選項的方法也幾乎一樣多。 你看,WordPress 允許插件作者在他們的設置頁面中創建他們自己的標記。 作為副作用,插件之間的設置頁面可能會有很大差異。
在本文中,我們將介紹使插件可配置的三種常用方法。 我們將首先創建一個設置頁面並使用默認的 WordPress 設置 API 創建我們的字段。
關於 SmashingMag 的進一步閱讀:
- 使用自定義字段擴展 WordPress
- WordPress的自定義字段黑客
- 使用您自己的控件擴展高級自定義字段
- 自定義帖子類型的完整指南
然後,我將引導您了解如何使用自定義處理程序設置您的字段。 最後,我將向您展示如何將出色的可配置字段插件高級自定義字段(ACF)集成到您自己的插件中。
由於這篇文章很長,這裡有一個目錄,其中包含指向每個主要部分的鏈接:
- 創建我們的插件和設置頁面
- 方法 1:使用內置的 WordPress 功能
- 方法 2:設置自定義表單和處理程序
- 方法 3:將 ACF(高級自定義字段)集成到您的插件中
有關代碼示例,請參閱我為這篇文章設置的存儲庫。
創建我們的插件和設置頁面
我們需要做的第一件事是設置我們的插件並創建一個設置頁面。 本文中概述的所有三種方法都從下面的插件結構開始。 此插件結構是面向對象的,因此如果您的插件是按程序編寫的,您自己的代碼可能會有一些差異。 特別注意動作和過濾器中的回調函數格式。
/* 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();
在我們的類中,我們將添加一個動作掛鉤來添加設置頁面:
public function __construct() { // Hook into the admin menu add_action( 'admin_menu', array( $this, 'create_plugin_settings_page' ) ); }
您可以看到我們的操作的回調是create_plugin_settings_page
,所以讓我們創建該方法。 注意:我已將參數設置為單獨的命名變量,以便為我們的代碼提供一些上下文,但您可以簡單地將值直接放在函數中以節省內存。
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 ); }
查看add_menu_page
的 WP codex 以獲取更多信息。
這個函數將創建我們的頁面以及菜單項。 這裡的重要部分是 slug、capability 和 callback 參數。 我們稍後將使用 slug 來註冊我們的字段,所以把它寫下來。 您可以更改功能以允許不同用戶級別訪問您的設置頁面。 至於回調,我們將很快創建該方法。 請注意,您還可以將 dashicon 類直接放入函數中以更改菜單的圖標。 最後一個參數是菜單項在菜單中的位置; 玩弄這個數字,在菜單中找到您希望設置下降的位置。 注意:您可以使用十進制值來避免與其他菜單項發生衝突。
我們的下一步是為我們的設置頁面創建回調方法plugin_settings_page_content
。
public function plugin_settings_page_content() { echo 'Hello World!'; }
如果您保存插件並刷新 WordPress 管理面板,您應該會看到以下內容:

您可以看到您的設置頁面是一個頂級菜單項。 根據設置頁面的需要,您可能更願意以這種方式保留它。 但是,您可能還希望將插件設置放在另一個菜單項下。 在這種情況下,您只需將create_plugin_settings_page
方法的最後一行更改為以下內容:
add_submenu_page( 'options-general.php', $page_title, $menu_title, $capability, $slug, $callback );
在這裡,我們將函數add_menu_page
更改為add_submenu_page
並添加一個新參數。 該參數是新設置頁面所在的父菜單項。 在add_submenu_page
文檔中,您可以看到一個非常好的父菜單項及其 slug 列表。 您可能還會看到我們不再有最後兩個參數$icon
和$position
。 由於我們現在在子菜單部分,我們不再控制元素的位置。 此外,子菜單沒有可用的圖標,因此不需要該參數。
如果您保存此新代碼,您將看到我們的設置頁面將顯示在“設置”菜單項下:

在許多情況下,添加插件設置頁面最合適的位置是在設置項下。 在 WordPress 法典中,它解釋說“設置”部分用於“顯示只有管理員才能查看的插件選項”。 但是,這只是一個指導方針,而不是規則。
現在我們已經設置了設置頁面並且我們知道如何移動項目,我們可以開始處理這些字段。 我們迄今為止所做的工作將被重用於下面的各種方法。
方法 1:使用內置的 WordPress 功能
在我們深入研究代碼之前,讓我們回顧一下使用這種方法的一些優點和缺點。
優點
- 易於集成到現有設置頁面
- 為您完成消毒
- 由於代碼由 WordPress 管理,因此不太可能中斷
- 可用於主題和插件
- 靈活、安全和可擴展
缺點
- 自定義數據驗證是手動的
- 高級字段類型(中繼器、地圖、上傳等)更難實現
什麼時候應該使用這種方法?
這種方法足夠靈活,可以針對非常簡單或非常高級的設置頁面進行定制。 如果您不介意手動執行某些操作,則可以在大多數情況下使用此方法。
入門
使用這種方法,我們需要遵循 WordPress 自己的選項頁面使用的相同標記。 我們應該修改我們的plugin_settings_page_content
方法如下:
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 }
上面的標記直接來自創建選項頁面的 WordPress 法典。 方法名稱應該與我們在上面的add_menu_page
函數中放置的回調名稱匹配。 包裝器div
實際上與默認的 WordPress 表單相同,並將從這些部分中提取樣式。 form
標籤指向 WordPress 的默認選項表單處理程序。
PHP 的三行代碼做了幾件事:
-
settings_fields
函數基本上是我們其他字段的參考。 您在該函數中輸入的字符串參數應該與我們之前設置的$slug
變量匹配——它將出現在我們稍後在插件中註冊的所有字段中。 此函數還為選項頁面的隨機數、表單操作和一些其他字段輸出一些隱藏輸入。 - 下一個函數
do_settings_sections
是我們將在插件其他地方註冊的部分和字段的佔位符。 - 最後一個函數
submit_button
將輸出提交輸入,但它也會根據頁面的狀態添加一些類。 您可能希望將其他參數傳遞給submit_button
函數; 法典中對它們進行了概述。
如果我們刷新設置頁面,我們應該會得到如下所示的內容:

看起來有點稀疏! 讓我們現在開始設置字段。
部分和字段
WordPress 將其選項頁面分成多個部分。 每個部分都可以有一個與之關聯的字段列表。 在開始添加字段之前,我們需要在插件中註冊一個部分。 將以下代碼添加到您的構造函數中:
add_action( 'admin_init', array( $this, 'setup_sections' ) );
這個鉤子將為我們的頁面設置部分。 這是回調的代碼:
public function setup_sections() { add_settings_section( 'our_first_section', 'My First Section Title', false, 'smashing_fields' ); }
第一個參數是該部分的唯一標識符,我們將把它用於我們希望分配給該部分的字段。 對於此頁面上的所有新部分,這些標識符應該是唯一的。 下一個參數是在該部分上方生成的標題——您可以將其設為任何您想要的。 第三個參數是回調。 現在我把它設置為false
,但我們很快就會重新討論這個問題。 第四個參數是將選項添加到的選項頁面(之前的$slug
變量)。
那麼為什麼我們的回調中有一個false
呢? 好吧,在使用他們的文檔設置 WordPress 選項時不太清楚的是,多個部分可以共享一個回調。 通常,當您設置回調時,掛鉤和回調之間存在一對一的關係。 舉個例子,讓我們嘗試使用相同的回調創建三個部分:
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' ); }
所有這三個部分都在第三個參數槽中設置了回調section_callback
。 如果我們然後創建一個與該回調匹配的方法並在其中放置一個“Hello World”:
public function section_callback( $arguments ) { echo '
你好世界
'; }
我們得到如下所示的東西:

我知道你在想什麼,“我為什麼要在我的所有部分下都有相同的文本?” 答案是你可能不會。 這是我們可以使用add_settings_section
函數有點棘手的地方。 如果您查看該函數的文檔,您會看到在頁面的註釋部分中,回調函數將被分配一個與我們的鉤子中的參數直接相關的參數數組。 如果你進去var_dump( $arguments )
你會看到所有的參數都被傳遞到我們的函數中。
然後,我們可以在回調中編寫一個簡單的開關,以根據傳入的 ID 更改文本:
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; } }
現在,我們可以在一個函數中更改每個部分的自定義文本!

當然,您也可以為這些部分指定唯一的回調,但是這種方法允許您將代碼合併到一個函數中。 這個想法同樣適用於設置字段。 我們可以讓我們所有的字段共享一個回調,並讓它根據我們傳入的參數輸出正確的字段類型。讓我們將字段添加到我們的構造函數方法中。 將此代碼放在構造函數中我們的部分掛鉤之後:
add_action( 'admin_init', array( $this, 'setup_fields' ) );
既然你已經知道演習,我只會給你我們行動的回調:
public function setup_fields() { add_settings_field( 'our_first_field', 'Field Name', array( $this, 'field_callback' ), 'smashing_fields', 'our_first_section' ); }
此函數中的參數類似於 section 函數中的參數。 第一個參數是字段的唯一標識符。 第二個是顯示在字段旁邊的標籤。 在第三個參數中,您可以看到我正在調用方法field_callback
; 我們將在一秒鐘內創建該回調。 第四個是我們想要使用的選項頁面(我們之前的$slug
)。 第五個參數是我們要分配此字段的部分的唯一標識符。
這是我們第三個參數中回調的代碼:
public function field_callback( $arguments ) { echo '<input name="our_first_field" type="text" value="' . get_option( 'our_first_field' ) . '" />'; }
在這裡,我只是將字段的唯一標識符複製到名稱、ID 和我們的get_option
函數中。 讓我們看看我們的頁面在附加了新字段後的樣子:

太棒了,我們在頁面上有我們的領域! 嘗試添加一些內容並點擊保存更改,我會在這裡等...
你做了嗎? 如果到目前為止您已完成所有操作,您應該會收到一條錯誤消息,例如ERROR: options page not found
或類似內容。 發生這種情況的原因實際上是 WordPress 中的一項安全功能。
你看,如果沒有這個功能,用戶可以進入 HTML 並將一個字段的名稱更改為他們想要的任何名稱,點擊保存,它會將該選項輸入到數據庫中,使用它給出的任何名稱(假設它是有效的)選項名稱)。 這可以允許任何用戶通過簡單地在字段中輸入正確的名稱並點擊保存來更改其他頁面上的選項(甚至是他們通常無法訪問的頁面)——這並不酷。
這個問題是通過添加一個名為register_setting
的函數來解決的。 除非您特別告訴 WordPress,“嘿,此字段允許保存在此頁面上”,否則 WordPress 不會更新數據庫中的字段。 所以在我們的字段標記下,我們將添加這個新功能。 這是我們添加代碼後回調的樣子:
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' ); }
新函數中的第一個參數是我們要保存字段的選項頁面(之前的$slug
),第二個參數是我們要保存的字段。 現在嘗試更新該字段——它成功了!
恭喜! 您剛剛使用 WordPress 設置 API 保存了您的第一個字段。 現在,如果我們想要一些不同的字段類型而不僅僅是文本怎麼辦? 讓我們重新審視我們的字段回調並討論$arguments
變量被傳遞到我們的函數中。
字段參數
如果我們進入我們的字段回調和var_dump( $arguments )
,我們將得到一個空數組。 是什麼賦予了? 在我們的部分回調中,我們得到了一堆關於該部分的東西。 好吧,這裡發生了一些不同的事情。 如果您查看add_settings_field
的文檔,則可以將第五個參數傳遞給函數。 該變量與回調中的$arguments
變量直接相關。 所以我們想要把我們的新東西放在那裡。
如果我們查看 WordPress 設置頁面中的默認字段之一,我們可以看到有幾個區域可以添加到我們的字段中以獲得一些默認格式。 這是常規設置頁面中時區字段的屏幕截圖:

使用這個字段作為起點,讓我們回顧一下我們想要傳遞給我們的字段回調的數據。
- 唯一標識符
- 字段的標籤(示例中的時區)
- 它應該進入哪個部分
- 字段類型(文本、文本區域、選擇等)
- 如果有多個選項,我們會想要那些
- 如果字段類型支持佔位符,則可能是佔位符
- 幫助文本(在示例中的字段右側)
- 補充文本(在示例中的字段下方)
- 如果有,可能是默認選擇
從這個列表中,我們可以設置一個關聯的字段和值數組,我們可以將它們傳遞給我們的回調:
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'] ); } }
所以我們在這裡的第一件事是一個名為$fields
的變量,它將保存我們想要創建的所有字段。 在該數組中,我們有另一個數組,用於保存每個字段的特定數據。 我已將數據設置為與上面的列表完全匹配。 然後,我遍歷數組中的每個字段(我們將很快添加更多)並添加字段並註冊它。 在add_settings_field
函數的末尾,我還為該特定字段添加了整個數據數組,以便我們可以在回調函數中做一些事情。 讓我們看看這裡的回調函數:
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 } }
在上面的例子中,我們做了幾件事。 如果字段為空,我們將為其設置默認值,並添加幫助和補充文本。 然而,我們代碼中最重要的部分是 switch 語句。 在此聲明中,我們將概述如何根據我們想要的字段類型處理我們的參數。
例如,如果我們有一個文本字段,我們就不需要有多個選項。 但是, <select>
下拉菜單必須有選項才能正常工作。 由於我們已經設置了文本類型,讓我們運行這段代碼,看看我們得到了什麼。

當您加載插件設置頁面時,您應該會在此圖像中看到頂部字段。 如果從字段中刪除內容(即佔位符),底部是您將看到的內容。 如果我要從我們的字段數組中刪除helper
器或supplimental
參數,它們應該會在設置頁面上消失。 我們還可以更改section
參數並在 section 中移動字段的位置。
好的,所以我們有文本字段; 一些更複雜的字段類型怎麼樣? 讓我們再看一下我們的 switch 語句,並為文本區域和單選添加選項:
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; }
在上面的代碼中,您會注意到每種字段類型之間的一些差異。 儘管文本區域在功能上與常規文本字段相似,但它們需要不同的標記。 由於選項的原因,選擇下拉菜單完全是另一種動物。 我們需要遍歷選項並設置值、選定狀態和標籤。 所以我們的標記是完全不同的。
現在我們已經更新了回調函數,讓我們看看字段數據是如何變化的:

$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' ) );
這是三個字段,每個字段在我們的插件中使用不同的字段類型。 第一個我們已經看過了。 第二個是我們新的textarea
字段。 我們可以向數組傳遞相同的參數(UID 除外),但是對我們的類型進行簡單的更改,我們將獲得一個textarea
。 此數組中的最後一個字段是選擇下拉菜單。 這裡的主要更新是添加了選項數組。 我們添加了一個簡單的關聯數組,其中數組鍵作為 HTML 選項值和標籤。 使用這個數組,我們的字段如下所示:

快完成了!
我們現在有一個正常工作的插件設置頁面。 我們已經為頁面、選項、所有回調設置了部分並註冊了字段。 唯一剩下的就是在別處獲取我們的設置值。 信不信由你,我們已經做到了。 在我們的字段回調頂部,您可以看到我們正在檢查數據庫值:
$value = get_option( $arguments['uid'] );
我們可以在我們的插件(或主題)中使用相同的代碼,只需將uid
傳遞給函數。 因此,如果我想獲得our_first_field
的值,我只需寫:
get_option('our_first_field')
嘿,快! 我們有很棒的插件和很棒的設置! 顯然我們只設置了幾個字段類型,但我已經完成並在代碼庫中為這種方法添加了更多(特別是文本字段、密碼、數字、文本區域、選擇下拉菜單、多選、單選按鈕和復選框)。
方法 2:設置自定義表單和處理程序
在過去,這種方法是添加設置頁面的唯一方法。 在 WordPress 2.7 之前,插件作者必須創建自己的自定義表單和處理程序。 這顯然導致了插件之間的許多錯誤和不一致。 雖然這種方法有些過時,但在某些情況下它仍然是一個可行的選擇。
優點
- 您可以將表單提交給自定義和遠程處理程序
- 您可以繞過一些內置的設置 API 限制
缺點
- 兼容性必須由開發人員維護
- 必須手動清理和驗證
什麼時候應該使用這種方法?
當您絕對必須擁有自定義處理程序或高度自定義的界面時,請使用此方法。 在大多數情況下,您可能可以使用方法 1,但您可以更靈活地使用此方法進行驗證和處理。
入門
在我們進入細節之前,我們需要想出一個我們將使用自定義處理程序的場景。 為簡單起見,讓我們製作一個表單來驗證用戶名和電子郵件地址。 我們可以從數據庫甚至遠程服務器中提取數據。 在這種情況下,我將設置一個包含有效用戶名和電子郵件地址的數組供我們檢查。 然後我們將存儲用戶輸入的字段值並將它們存儲在數據庫中。
創建表單
就像我之前提到的,我們將遵循我們在“創建我們的插件和設置頁面”中所做的相同步驟。 對於這種方法,我們將使用靜態 HTML 標記設置我們的字段。 我們將此代碼添加到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 }
您可以在上面看到我們只是為我們的字段添加了一些靜態 HTML。 我們正在從核心 WordPress 設置頁面複製標記。 我們還省略了表單操作,以便它將表單提交到當前頁面,而不是默認的options.php處理程序。
在我們編寫自定義處理程序之前,讓我們加入一些快速的安全功能。 我們應該做的第一件事是在我們的表單中添加一個隨機數。 Nonce 將防止跨站點請求偽造嘗試,這類似於用戶欺騙或重放攻擊。 讓我們將 nonce 放入我們的 HTML 中:
<form method="POST"> <?php wp_nonce_field( 'awesome_update', 'awesome_form' ); ?> <table class="form-table">
wp_nonce_field
將為我們的表單添加幾個隱藏字段; 隨機數和推薦人。 當我們瀏覽處理程序代碼時,我們將回到隨機數。
接下來我們需要添加一個字段來檢測表單何時更新。 我們可以通過簡單地在表單頂部添加一個隱藏字段來做到這一點:
<form method="POST"> <input type="hidden" name="updated" value="true" /> <?php wp_nonce_field( 'awesome_update', 'awesome_form' ); ?> <table class="form-table">
現在我們可以在頁面頂部放置一段代碼來檢測表單何時提交並將我們發送到自定義處理程序:
public function plugin_settings_page_content() { if( $_POST['updated'] === 'true' ){ $this->handle_form(); } ?> <div class="wrap"> <h2>My Awesome Settings Page</h2>
在這裡,我們只是檢查隱藏的updated
字段是否已提交,如果已提交,我們在插件中調用一個名為handle_form
的方法。 這是我們可以開始編寫自定義處理程序的地方。
創建處理程序
在我們實際管理表單數據之前,我們需要在處理程序中檢查幾件事。 我們首先需要檢查我們的 nonce 是否存在並且有效:
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 } }
上面的代碼驗證隨機數是否正確。 如果它是無效的,我們會給用戶一個關於為什麼表單沒有更新的消息。 如果 nonce 存在並且正確,我們可以處理我們的表單。 現在讓我們為表單處理程序編寫代碼(此代碼將替換上面片段中的註釋):
$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 }
讓我們看一下本節中的代碼。 前幾行是我們將檢查的有效用戶名/電子郵件數組。 這些數組值可以從任何地方填充。
接下來的兩行是我們的用戶在表單中輸入的值。 我們正在使用 WordPress 提供的內置清理功能。 此步驟對於避免 Web 表單的多個漏洞非常重要。 接下來,我們檢查用戶提供的值是否在我們的可接受值數組中。 如果是,請更新數據庫中的表單選項。 此步驟也可以用自定義存儲機制替換。 我們還給用戶一條消息,表明他們的字段已保存。 如果用戶的輸入無效,我們會告訴他們。
我們需要做的最後一件事是在輸入後在表單中顯示存儲的字段。 我們將以與在插件的其他地方檢索這些字段相同的方式執行此操作:使用get_option
函數。 以下是我們添加正確代碼後的字段:
<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>
現在我們準備好測試我們的表單了。 嘗試輸入用戶名admin和電子郵件地址[email protected] 。 您應該在您的表格上獲得以下信息:

如果您嘗試將任一字段設置為無效值,您應該會收到一條錯誤消息,並且由於我們的自定義處理程序,這些字段不應更新。
這就是我們的第二種方法! 您現在已經設置了一個自定義表單和處理程序來管理您的插件字段。 此方法的完整代碼可在本文的存儲庫中找到。 現在,讓我們繼續我們的最終方法。
方法 3:將 ACF(高級自定義字段)集成到您的插件中
如果你還沒有使用過 Elliot Condon 的 ACF,讓我來介紹一下。 ACF 是一個出色的 WordPress 現場經理。 關於它的最好的事情之一是現場配置界面。 它可以很容易地為 WordPress 中的許多不同頁面(例如帖子、頁面、用戶、分類,甚至是他們自己的集成選項頁面)創建字段。 你可能會想“我不能把別人的插件集成到我自己的——這太陰暗了!” 但是 Condon 先生了解他的開發人員同事的困境,並在他的插件中對此進行了計劃。 您可以查看他關於此主題的文檔,但我將在這裡重申其中的一些內容。 讓我們回顧一下規則。
- 首先,如果您要分發免費插件,則必須使用 ACF 的免費版本。 這樣一來,人們就無法從您的免費插件中獲取 PRO 版本——這並不酷。 您可以在高級插件和主題中使用 PRO 版本沒問題,只要確保您購買了開發者許可證。
- 其次,不要修改 ACF 的版權信息。 給這個人一些信任!
- 最後,不要將許可證密鑰與您的插件一起分發。
現在,這種方法的優缺點:
優點
- 很容易集成到主題和插件中
- 您可以利用 ACF 中的高級字段
- 代碼和安全更新由 ACF 團隊管理
- 如果您遇到困難,ACF 有很棒的插件和支持
- 由於字段配置 UI,配置字段非常簡單
缺點
- 對標記的訪問受限
- 為您的插件或主題創建依賴項
- 要使 ACF 保持最新,您必須在插件/主題文件中保持更新(更多信息見下文)
什麼時候應該使用這種方法?
當您想快速構建高級設置界面並且不需要自定義外觀時。
入門
對於這種方法,我將向您展示如何為 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 (查看大圖)
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 ); }
我們函數的前兩行是添加設置字段所需的腳本和样式。 之後,我們正在為我們的表單配置選項。 您可能會注意到field_groups
參數中的值與我們的register_field_group
函數中的 ID 匹配。 要查看其他配置參數,請查看acf_form
文檔。 我們函數的最後一行實際上是要渲染表單。
如果您現在嘗試加載設置頁面,您可能會看到該頁面實際上已損壞。 這是因為 ACF 需要為 JavaScript 本地化一些變量。 為此,我們需要在構造函數中添加另一個鉤子:
add_action( 'admin_init', array( $this, 'add_acf_variables' ) );
現在我們需要設置回調:
public function add_acf_variables() { acf_form_head(); }
您可以嘗試添加一些內容並保存,它應該像我們的其他兩種方法一樣工作。 我們的頁面應該是這樣的:

我們需要解決的只是幾個清理項目:
您可能想要隱藏您正在為插件使用 ACF 的事實。 如果是這種情況,您需要隱藏自定義字段菜單項。 您可以通過將此代碼段添加到您的構造函數來做到這一點:
add_filter( 'acf/settings/show_admin', '__return_false' );
我們應該刪除字段組的數據庫版本。 只需轉到自定義字段部分並點擊垃圾桶按鈕。 此步驟是可選的,因為它只會影響您構建插件的環境,但如果您在同一環境中測試插件,它可能會引入問題。
在插件中使用 ACF 字段
要獲取您創建的 ACF 字段,您只需使用默認的 ACF get_field
函數。 第一個選項應該是字段的唯一 ID,第二個參數設置為'option'
。 下面是我們如何獲得Awesome Date字段:
get_field( 'awesome_date', 'option' )
就是這樣。 您現在已經設置了一個帶有 ACF 設置的插件! 您可以在存儲庫中查看此方法的代碼。
結論
所以你有它:使你的插件可配置的三種方法。 我很想听聽您可以使用這些方法創建的插件。 再一次,我建立了一個存儲庫,其中包含每種方法的代碼。 請隨意分叉它們並定制它們以滿足您自己的需求。
至於我個人對這些方法的偏好,我傾向於方法 1。我更喜歡在我的插件中保留盡可能少的依賴項,並且您可以自定義標記以主題化自定義項目的設置頁面。 對於快速原型或需要設置非常高級字段的項目,我將使用 ACF——但它增加了管理插件更新的複雜性。
還值得一提的是 Scott Clark 提出的 Fields API 提案。 雖然目前仍在進行中,但 API 本質上將允許插件和主題開發人員使用與定制器 API 相同的界面在管理面板的其他區域創建設置字段。
ACF 替代品
正如下面評論中所指出的,為了給開發人員提供與 ACF 方法類似的其他選項,您可以查看一些可能提供不同功能的替代方案。 如果您還有更多,請在下面的評論中提交! 在這裡,它們沒有特別的順序:
- WebDevStudios 的 CMB2
- Tran Ngoc Tuan Anh ( Rilwis ) 的 Meta Box