Professional WordPress Plugin Development. Brad Williams
and <p> tags
type: Type of message, error or update
You can improve the validating function with a user notice if applicable, as shown here:
<?php function pdev_plugin_validate_options( $input ) { $valid['name'] = preg_replace( '/[^a-zA-Z\s]/', '', $input['name'] ); if( $valid['name'] !== $input['name'] ) { add_settings_error( 'pdev_plugin_text_string', 'pdev_plugin_texterror', 'Incorrect value entered! Please only input letters and spaces.', 'error' ); } return $valid; } ?>
The function now compares the validated data with the original input and displays an error message if they differ (see Figure 3‐5).
FIGURE 3‐5: Error message
Expanding with Additional Field Types
You've now covered the different ways to create a settings page using the WordPress Settings API. Let's expand on that by adding additional form field types to your settings page. This is a more real‐world example showing how elaborate your settings page could be. At the end of this section, you'll review the entire plugin code as a whole.
First, you need to define additional settings fields using the add_settings_field()
function. The following example updates the registration of those fields in your custom pdev_plugin_admin_init()
function:
// Register and define the settings add_action('admin_init', 'pdev_plugin_admin_init'); function pdev_plugin_admin_init(){ //define the setting args $args = array( 'type' => 'string', 'sanitize_callback' => 'pdev_plugin_validate_options', 'default' => NULL ); //register our settings register_setting( 'pdev_plugin_options', 'pdev_plugin_options', $args ); //add a settings section add_settings_section( 'pdev_plugin_main', 'PDEV Plugin Settings', 'pdev_plugin_section_text', 'pdev_plugin' ); //create our settings field for name add_settings_field( 'pdev_plugin_name', 'Your Name', 'pdev_plugin_setting_name', 'pdev_plugin', 'pdev_plugin_main' ); //create our settings field for favorite holiday add_settings_field( 'pdev_plugin_fav_holiday', 'Favorite Holiday', 'pdev_plugin_setting_fav_holiday', 'pdev_plugin', 'pdev_plugin_main' ); //create our settings field for beast mode add_settings_field( 'pdev_plugin_beast_mode', 'Enable Beast Mode?', 'pdev_plugin_setting_beast_mode', 'pdev_plugin', 'pdev_plugin_main' ); }
As you can see in the preceding code sample, you register two new form fields for Favorite Holiday and Beast Mode. Both call custom functions for displaying each field on your settings page. Let's look at the pdev_plugin_setting_fav_holiday()
function first.
// Display and select the favorite holiday select field function pdev_plugin_setting_fav_holiday() { // Get option 'fav_holiday' value from the database // Set to 'Halloween' as a default if the option does not exist $options = get_option( 'pdev_plugin_options', [ 'fav_holiday' => 'Halloween' ] ); $fav_holiday = $options['fav_holiday']; // Define the select option values for favorite holiday $items = array( 'Halloween', 'Christmas', 'New Years' ); echo "<select id='fav_holiday' name='pdev_plugin_options[fav_holiday]'>"; foreach( $items as $item ) { // Loop through the option values // If saved option matches the option value, select it echo "<option value='" .$item. "' " .selected( $fav_holiday, $item, false ).">" . esc_html( $item ) . "</option>"; } echo "</select>"; }
This example registers a new select drop‐down field allowing the user to select their favorite holiday. First, you call get_option()
to load the current setting value, if it exists. If the value does not exist, meaning the user has not selected and saved the selection yet, the default is set to Halloween
. Next you set the $items
variable to an array of available holiday options to choose from.
Now it's time to loop through the available holiday options and display each one in the drop‐down field. We're using the WordPress core function selected()
, which compares two values and, if they match, returns selected="selected"
, which will select that option value in the drop‐down.
Now let's look at the custom function for displaying the radio button field, pdev_plugin_setting_beast_mode()
.
// Display and set the Beast Mode radio button field function pdev_plugin_setting_beast_mode() { // Get option 'beast_mode' value from the database // Set to 'disabled' as a default if the option does not exist $options = get_option( 'pdev_plugin_options', [ 'beast_mode' => 'disabled' ] ); $beast_mode = $options['beast_mode']; // Define the radio button options $items = array( 'enabled', 'disabled' ); foreach( $items as $item ) { // Loop the two radio button options and select if set in the option value echo "<label><input ".checked( $beast_mode, $item, false )." value= '" . esc_attr( $item ) . "' name='pdev_plugin_options[beast_mode]' type='radio'/>" . esc_html( $item ) . "</label><br/>"; } }
This example registers a new radio button field allowing the user to select if they want to enable beast mode or not. Again, you'll use get_option()
to load the current setting value, and if it doesn't exist, the default value disabled
is set. Next, you'll define the two values in the $items
array. Now you need to loop through the two options displaying the radio button. The checked()
function is used to compare the saved value against the display value and, if they are the same, to input checked="checked"
on the radio button form field.
Now that you have registered two new settings fields and created the custom functions to display both fields, you need to update your validate function to accept those values and sanitize them as needed.
// Validate user input for all three options function pdev_plugin_validate_options( $input ) { // Only allow letters and spaces for the name $valid['name'] = preg_replace( '/[^a-zA-Z\s]/', '', $input['name'] ); if( $valid['name'] !== $input['name'] ) { add_settings_error( 'pdev_plugin_text_string', 'pdev_plugin_texterror', 'Incorrect value entered! Please only input letters and spaces.', 'error' ); } // Sanitize the data we are receiving $valid['fav_holiday'] = sanitize_text_field( $input['fav_holiday'] ); $valid['beast_mode'] = sanitize_text_field( $input['beast_mode'] ); return $valid; }
The only update here is to run the two new option values through the sanitize_text_field()
WordPress function to sanitize the user‐inputted data. Even though the values are hard‐coded in the form, that doesn't stop a user from modifying the frontend form code and posting unknown data to these setting fields. You'll cover this more in Chapter 4.
That's it! You now have a more robust settings page for your plugin. Let's review the entire plugin source code with your new settings fields.
<?php /* Plugin Name: Settings API example - Multiple Fields Plugin URI: https://example.com/ Description: A complete and practical example of the WordPress Settings API Author: WROX Author URI: http://wrox.com */ // Add a menu for our option page add_action( 'admin_menu', 'pdev_plugin_add_settings_menu' ); function pdev_plugin_add_settings_menu() { add_options_page( 'PDEV Plugin Settings', 'PDEV Settings', 'manage_options', 'pdev_plugin', 'pdev_plugin_option_page' ); } // Create the option page function pdev_plugin_option_page() { ?> <div class="wrap"> <h2>My plugin</h2> <form action="options.php" method="post"> <?php settings_fields( 'pdev_plugin_options' ); do_settings_sections( 'pdev_plugin' ); submit_button( 'Save Changes', 'primary' ); ?> </form> </div> <?php } // Register and define the settings add_action('admin_init', 'pdev_plugin_admin_init'); function pdev_plugin_admin_init(){ // Define the setting args $args = array( 'type' => 'string', 'sanitize_callback' => 'pdev_plugin_validate_options', 'default' => NULL ); // Register our settings register_setting( 'pdev_plugin_options', 'pdev_plugin_options', $args );