In this part, we will add a settings page for our plugin GCMovie
. In the settings page, there will be a field for the user to set whether to delete all the movie posts on uninstall. It looks like this:
As what is mentioned on WordPress plugin handbook- Settings , WordPress provides two set of APIs that can help us to add a settings page semi-automatically. They do make us do less work and bring some other benefits like consistent display and robustness, but we need to take some time to figure out how to use these APIs.
- Settings API, create and manage the form data.
Add or remove an option in wp_options table of the database.
- register_setting(), register a setting and its data. It also creates a new entry in wp_options table.
- unregister_setting()
Add sections or fields to a settings page.
Output the settings page.
- settings_fields(), output nonce, action, and option_page fields for a settings page.
- do_settings_sections(), print out all settings sections and fields added to a particular settings page.
- add_settings_error()
- settings_errors()
…
- Options API, get and set option values from or and the database with a key-value style.
Image how we build a settings page without such help. First we register a new page to the parent menu, in the page we read old option values if existing from the database and display them in a form. Then we need to handle the form submission to write the new values back to the database. A process can be automated somehow, isn’t it? After such a thinking , it helps to understand the ideas behind these two set APIs. But probably you make it clear till you finish all the whole example.
Parts of the rough process to build a settings page with Setting API and Options API would be:
- Add a new page to the GCMovie’s menu with
add_submenu_page()
.// Add a new page "gcmovie_settings" add_submenu_page( $parent, esc_html__( 'Settings', 'gcmovie' ), esc_html__( 'Settings', 'gcmovie' ), 'manage_options', 'gcmovie_settings', // menu_slug array( $this, 'show_page' ) // callback to display the page );
- Register a new setting with
register_setting()
, it will also create an entry in the wp_options table.// Register a new setting 'gcmovie_options' for "gcmovie_settings" page register_setting( 'gcmovie_settings', // option group, correspond to an allowed option key name 'gcmovie_options', // option name array( $this, 'sanitize' ) // callback to sanitize the option's value );
You may specify more arguments like the type, description or default value for the option.
Here it will create an option with name “gcmovie_options”, the value of the option can be a single value or an array object ( in database it is converted to a json) which can hold multiple key-value pairs.
- Add new sections to the existing page with add_settings_section().
// Add a new section "gcmovie_settings_section" to "gcmovie_sttings" page add_settings_section( 'gcmovie_settings_section', // id, identify the section. __( 'After uninstall', 'gcmovie' ), // title array( $this, 'display_section' ), // callback to display html for the seciton 'gcmovie_settings' // page );
- Add new fields to existing sections with add_settings_field().
// Add a new filed to section "gcmovie_settings_section" add_settings_field( 'gcmovie_settings_field', // id to identify the field. // As of WP 4.6 this value is used only internally // Use $args's "label_for" to populate the id inside the callback __( 'Delete movies', 'gcmovie' ), // title array( $this, 'display_field' ), // callback to display html for an option 'gcmovie_settings', // page 'gcmovie_settings_section', // section [ // $args 'label_for' => 'delete_movies_after_uninstall', // It is used to populate the "for" attribute of <label> // that wraps the title ] );
Now let’s start our work.
Create a setting class
Create a file named class-gcmovie-setting.php
under inc
folder and add below code:
<?php
/*
* GCMovie setting page
*/
if ( ! defined( 'WPINC' ) ) {
die( 'No direct access.' );
}
class GCMovie_Setting {
}
Register a setting page to menu
Add below function to GCMovie_Setting
to add a setting page to our GCMovie menu.
function register_pages() {
$parent = 'edit.php?post_type=gcmovie';
// Settings page
add_submenu_page(
$parent,
esc_html__( 'Settings', 'gcmovie' ),
esc_html__( 'Settings', 'gcmovie' ),
'manage_options',
'gcmovie_settings',
array( $this, 'show_page' )
);
}
Register “admin_init” action
Add a constructor function and inside it register an callback to admin_init
action. For register_setting() and add_settings_*()
functions should all be added to the admin_init
action hook.
function __construct() {
add_action( 'admin_init', array( $this, 'register_setting' ) );
}
Register a new setting
In the callback register_setting()
, we register a new setting, add a new section to the page and add a field to the section.
function register_setting() {
// Register a new setting with option_group, option_name and a santize callback
// which is used to sanitize the option's value before saving it to database.
register_setting( 'gcmovie_settings', 'gcmovie_options', array( $this, 'sanitize' ) );
add_settings_section(
'gcmovie_settings_section',
__( 'After uninstall', 'gcmovie' ),
array( $this, 'display_section' ),
'gcmovie_settings'
);
add_settings_field(
'gcmovie_settings_field', // As of WP 4.6 this value is used only internally
// Use $args' label_for to populate the id inside the callback
__( 'Delete movies', 'gcmovie' ),
array( $this, 'display_field' ),
'gcmovie_settings',
'gcmovie_settings_section',
[
'label_for' => 'delete_movies_after_uninstall', // id of the option
]
);
}
Sanitize the option’s value before saving it to database
Add our sanitize function to sanitize the option’s value.
function sanitize( $input ) {
$new_input = array();
$name = 'delete_movies_after_uninstall';
$new_input[$name] = ( isset( $input[$name] ) && $input[$name] == '1' ) ? '1' : '0';
return $new_input;
}
Display the section and field
Implement the two callbacks to separately display the section and the filed we added.
Focus on the display_field()
function and try to get to know how we display the field with the information we set when adding the filed, and how to get the old value of the option.
function display_field( $args ) {
// Get the value of the setting we've registered with register_setting()
$options = get_option( 'gcmovie_options' );
?>
<label for="<?php echo esc_attr( $args['label_for'] ); ?>">
<input id="<?php echo esc_attr( $args['label_for'] ); ?>" name="gcmovie_options[<?php echo esc_attr( $args['label_for'] ); ?>]" type="checkbox" value="1" <?php echo ( isset( $options[$args['label_for']] ) && $options[$args['label_for']] == "1" ) ? 'checked' : ''; ?>>
<?php _e( 'Delete moives after uninstall', 'gcmovie' ) ?>
</label>
<?php
}
Display the settings page
Add our callback to display the settings page. In this function, we check the user’s capabilities, handle error messages, and then call three functions to show the the page:
settings_fields()
, output some hidden input fields, like option_page, action, nonce.do_settings_sections()
, output sections and fields added to the page.submit_button()
, output a submit button, with provided text and appropriate class(es).
function show_page() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
// Add error/update messages
// Check if the user have submitted the settings,
// WordPress will add the "settings-updated" $_GET parameter to the url
if ( isset( $_GET['settings-updated'] ) ) {
// Add settings saved message with the class of "updated"
add_settings_error( 'gcmovie_settings', 'gcmovie_message', __( 'Settings Saved', 'gcmovie' ), 'updated' );
}
// Show error/update messages
settings_errors( 'gcmoive_settings' );
?>
<div class="wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
<form action="options.php" method="post">
<?php
settings_fields( 'gcmovie_settings' ); // Output security fields for the registered setting "gcmovie_settings".
do_settings_sections( 'gcmovie_settings' ); // Output setting sections and their fields registed before.
submit_button( __( 'Save Settings', 'gcmovie' ) ); // Output save settings button.
?>
</form>
</div>
<?php
}
Define init mthod and initiate an instance
Define init
method to initiate an instance of GCMoview_Setting
and call it at the end of the file outside GCMovie_Shortcode
class.
class GCMovie_Setting {
//...
static function init() {
new GCMovie_Admin;
}
//...
}
GCMovie_Setting::init();
Include the file in admin file
We organize the settings as part of GC_Admin
, so include the file into it. In class-gcmovie-admin.php
file, add below code to the constructor function of GCMovie_Admin
class. Therefore our setting code will take effect.
require_once GCMOVIE_PLUGIN_DIR . 'inc/class-gcmovie-setting.php';
$gcmovie_setting = new GCMovie_Setting;
add_action( 'admin_menu', array( $gcmovie_setting, 'register_pages' ) );
Now the constructor looks like:
function __construct() {
add_filter( 'manage_gcmovie_posts_columns', array( $this, 'custom_table_columns' ) );
add_action( 'manage_gcmovie_posts_custom_column' , array( $this, 'custom_table_column' ), 10, 2 );
require_once GCMOVIE_PLUGIN_DIR . 'inc/class-gcmovie-setting.php';
$gcmovie_setting = new GCMovie_Setting;
add_action( 'admin_menu', array( $gcmovie_setting, 'register_pages' ) );
}