Skip to content

Creating a Custom WordPress Settings Page: A Beginner's Guide

Learn how to build a custom WordPress settings page with a select field, text input, and checkboxes, then save the values to the database.

7 min read
An abstract WordPress settings panel with a dropdown, text field, toggles and save button
On this page9 sections

For developers looking to extend the functionality of WordPress, creating a custom settings page can be a crucial skill. This allows you to offer your users a dedicated area where they can configure options for your theme or plugin. In this guide, we’ll walk through how to create a settings page that includes a select field, text field, and checkbox, explaining how to display these on the page and save the input to the database.

Step 1: Create a new PHP file in your WordPress theme or plugin directory and name it something like “word-count-settings.php“.

Step 2: Define the WordCountAndTimePlugin class. The class name can be anything. For now, we’re defining it WordCountAndTimePlugin.

  • The code defines a class called ‘WordCountAndTimePlugin’ using the ‘class’ keyword.
Step 2 · word-count-settings.php
class WordCountAndTimePlugin
{
// ... Constructor and methods will go here ...
}

Step 3: Initialize the class

  • Inside the class, a constructor function is defined using the ‘__construct‘ method.

  • The constructor function adds two actions: ‘admin_menu‘ and ‘admin_init‘.

  • The ‘admin_menu‘ action is used to add a new options page to the WordPress admin menu.

  • The ‘admin_init‘ action is used to initialize the plugin settings.

Step 3 · word-count-settings.php
class WordCountAndTimePlugin
{
function __construct()
{
add_action('admin_menu', array($this, 'adminPage'));
add_action('admin_init', array($this, 'settings'));
}
}

Step 4: Define the settings function

  • The ‘settings‘ function is defined to handle the plugin settings.

  • Inside this function, several settings fields are added using the ‘add_settings_field‘ function.

  • Each setting field has a unique name, label, and HTML callback function.

  • The ‘register_setting‘ function is used to register each setting field, specifying the sanitize callback function and default value.

Step 4 · word-count-settings.php
class WordCountAndTimePlugin
{
function __construct()
{
add_action('admin_menu', array($this, 'adminPage'));
add_action('admin_init', array($this, 'settings'));
}
function settings()
{
add_settings_section('wcp_first_section', null, null, 'word-count-settings-page');
// Select
add_settings_field('wcp_location', 'Display Location', array($this, 'locationHtml'), 'word-count-settings-page', 'wcp_first_section');
register_setting('wordcountplugin', 'wcp_location', array('sanitize_callback' => array($this, 'sanitizeLocation'), 'default' => '0'));
// Text Field
add_settings_field('wcp_headline', 'Headline Text', array($this, 'headlineHtml'), 'word-count-settings-page', 'wcp_first_section');
register_setting('wordcountplugin', 'wcp_headline', array('sanitize_callback' => 'sanitize_text_field', 'default' => 'Post Statistics'));
// Checkbox
add_settings_field('wcp_wordcount', 'Word Count', array($this, 'checkboxHtml'), 'word-count-settings-page', 'wcp_first_section', array('theName' => 'wcp_wordcount'));
register_setting('wordcountplugin', 'wcp_wordcount', array('sanitize_callback' => 'sanitize_text_field', 'default' => '1'));
add_settings_field('wcp_charactercount', 'Character Count', array($this, 'checkboxHtml'), 'word-count-settings-page', 'wcp_first_section', array('theName' => 'wcp_charactercount'));
register_setting('wordcountplugin', 'wcp_charactercount', array('sanitize_callback' => 'sanitize_text_field', 'default' => '1'));
add_settings_field('wcp_readtime', 'Read Time', array($this, 'checkboxHtml'), 'word-count-settings-page', 'wcp_first_section', array('theName' => 'wcp_readtime'));
register_setting('wordcountplugin', 'wcp_readtime', array('sanitize_callback' => 'sanitize_text_field', 'default' => '1'));
}
}

A note on $args. In this code, 'theName' => 'wcp_wordcount' is an argument passed to the checkboxHtml callback. Inside checkboxHtml, it is available as $args['theName']. This lets us reuse one callback for several settings fields while still telling each checkbox apart.

Step 5: Define the sanitizeLocation function

When we need to deal with custom validation logic for a particular field, we can create a custom sanitization function like this.

  • The ‘sanitizeLocation‘ function is defined to sanitize the select input for the ‘wcp_location‘ setting.

  • It checks if the input value is either 0 or 1.

  • If the input value is invalid, an error message is added and the function returns the current value of ‘wcp_location‘.

Step 5 · word-count-settings.php
// Sanitize the select input i.e. location value validation
function sanitizeLocation($input)
{
if ($input != 0 && $input != 1) {
add_settings_error('wcp_location', 'wcp_location_error', 'Display location must be beginning or end.');
return get_option('wcp_location');
}
return $input;
}

Step 6: Define the HTML callback functions

  • Three HTML callback functions are defined: ‘locationHtml‘, ‘headlineHtml‘, and ‘checkboxHtml‘.

  • These functions generate the HTML markup for the select input, text input, and checkbox input fields, respectively.

Step 6 · word-count-settings.php
// Handle the select input HTML
function locationHtml()
{ ?>
<select name="wcp_location">
<option value="0" <?php selected(esc_attr(get_option('wcp_location')), 0); ?>>Beginning of Post</option>
<option value="1" <?php selected(esc_attr(get_option('wcp_location')), 1); ?>>End of Post</option>
</select>
<?php }
// Handle the text input HTML
function headlineHtml()
{ ?>
<input type="text" name="wcp_headline" value="<?php echo esc_attr(get_option('wcp_headline')); ?>">
<?php }
// Handle the checkbox input HTML
function checkboxHtml($args)
{ ?>
<input type="checkbox" name="<?php echo $args['theName']; ?>" value="1" <?php checked(esc_attr(get_option($args['theName'])), 1); ?>>
<?php }

Step 7: Define the adminPagefunction

  • The ‘adminPage‘ function is defined to generate the HTML markup for the options page.

  • It uses the ‘add_options_page‘ function to add a new options page to the WordPress admin menu.

  • The function specifies the page title, menu title, capability required to access the page, and the HTML callback function.

Step 7 · word-count-settings.php
function adminPage()
{
add_options_page('Word Count Settings', 'Word Count', 'manage_options', 'word-count-settings-page', array($this, 'ourHtml'));
}

Step 8: Define the ourHTMLfunction

  • The ‘ourHTML‘ function is defined to generate the HTML markup for the options page content.

  • It includes a form with the ‘action‘ attribute set to ‘options.php‘ and the ‘method‘ attribute set to ‘POST‘.

  • Inside the form, the ‘settings_fields‘ function is used to output the hidden fields required for the settings.

  • The ‘do_settings_sections‘ function is used to output the sections and fields defined in the ‘settings’ function.

  • Finally, the ‘submit_button‘ function is used to output the submit button.

Step 8 · word-count-settings.php
function ourHTML()
{ ?>
<div class="wrap">
<h1>Word Count Settings</h1>
<form action="options.php" method="POST">
<?php
settings_fields('wordcountplugin');
do_settings_sections('word-count-settings-page');
submit_button();
?>
</form>
</div>
<?php }

Step 9: Create an instance of the WordCountAndTimePlugin class

  • Outside the class definition, an instance of the ‘WordCountAndTimePlugin’ class is created.

  • This will initialize the plugin and execute the constructor function.

Step 9 · word-count-settings.php
$wordCountAndTimePlugin = new WordCountAndTimePlugin();

Now that we’ve explored how to create a settings page within WordPress, here is the complete code snippet you would use for a plugin that adds a settings page with select, text, and checkbox fields. This code is designed to get you started on building your own customized settings for your WordPress plugins.

Complete plugin · word-count-settings.php
<?php
/*
Plugin Name: Our First Unique Plugin
Plugin URI: https://www.rajandangi.com.np
Description: This is our first unique plugin
Author: Rajan Dangi
Version: 1.0
Author URI: https://www.rajandangi.com.np
Text Domain: wcdomain
Domain Path: /languages
*/
class WordCountAndTimePlugin
{
function __construct()
{
add_action('admin_menu', array($this, 'adminPage'));
add_action('admin_init', array($this, 'settings'));
add_action('init', array($this, 'languages'));
}
function languages()
{
load_plugin_textdomain('wcdomain', false, dirname(plugin_basename(__FILE__)) . '/languages');
}
function settings()
{
add_settings_section('wcp_first_section', null, null, 'word-count-settings-page');
// Select
add_settings_field('wcp_location', esc_html__('Display Location', 'wcdomain'), array($this, 'locationHtml'), 'word-count-settings-page', 'wcp_first_section');
register_setting('wordcountplugin', 'wcp_location', array('sanitize_callback' => array($this, 'sanitizeLocation'), 'default' => '0'));
// Text Field
add_settings_field('wcp_headline', 'Headline Text', array($this, 'headlineHtml'), 'word-count-settings-page', 'wcp_first_section');
register_setting('wordcountplugin', 'wcp_headline', array('sanitize_callback' => 'sanitize_text_field', 'default' => 'Post Statistics'));
// Checkbox
add_settings_field('wcp_wordcount', 'Word Count', array($this, 'checkboxHtml'), 'word-count-settings-page', 'wcp_first_section', array('theName' => 'wcp_wordcount'));
register_setting('wordcountplugin', 'wcp_wordcount', array('sanitize_callback' => 'sanitize_text_field', 'default' => '1'));
add_settings_field('wcp_charactercount', 'Character Count', array($this, 'checkboxHtml'), 'word-count-settings-page', 'wcp_first_section', array('theName' => 'wcp_charactercount'));
register_setting('wordcountplugin', 'wcp_charactercount', array('sanitize_callback' => 'sanitize_text_field', 'default' => '1'));
add_settings_field('wcp_readtime', 'Read Time', array($this, 'checkboxHtml'), 'word-count-settings-page', 'wcp_first_section', array('theName' => 'wcp_readtime'));
register_setting('wordcountplugin', 'wcp_readtime', array('sanitize_callback' => 'sanitize_text_field', 'default' => '1'));
}
// Sanitize the select input i.e. location value validation
function sanitizeLocation($input)
{
if ($input != 0 && $input != 1) {
add_settings_error('wcp_location', 'wcp_location_error', 'Display location must be beginning or end.');
return get_option('wcp_location');
}
return $input;
}
// Handle the select input HTML
function locationHtml()
{ ?>
<select name="wcp_location">
<option value="0" <?php selected(esc_attr(get_option('wcp_location')), 0); ?>>Beginning of Post</option>
<option value="1" <?php selected(esc_attr(get_option('wcp_location')), 1); ?>>End of Post</option>
</select>
<?php }
// Handle the text input HTML
function headlineHtml()
{ ?>
<input type="text" name="wcp_headline" value="<?php echo esc_attr(get_option('wcp_headline')); ?>">
<?php }
// Handle the checkbox input HTML
function checkboxHtml($args)
{ ?>
<input type="checkbox" name="<?php echo $args['theName']; ?>" value="1" <?php checked(esc_attr(get_option($args['theName'])), 1); ?>>
<?php }
function adminPage()
{
add_options_page('Word Count Settings', __('Word Count', 'wcdomain'), 'manage_options', 'word-count-settings-page', array($this, 'ourHtml'));
}
function ourHTML()
{ ?>
<div class="wrap">
<h1>Word Count Settings</h1>
<form action="options.php" method="POST">
<?php
settings_fields('wordcountplugin');
do_settings_sections('word-count-settings-page');
submit_button();
?>
</form>
</div>
<?php }
}
$wordCountAndTimePlugin = new WordCountAndTimePlugin();
// Implement Word Count and Time Plugin on the front end of the website using the_content filter
require_once plugin_dir_path(__FILE__) . 'inc/word-count.php';

WordPress settings page in the admin dashboard

Actual Output

Browse the GitHub Repository

Filed underWeb DevelopmentPHPWordpressplugin development
Share

Rajan Dangi

Senior Web Developer

Senior web developer at SathiSoft. I write about PHP, Python, Linux and the practical details of building for the web.

More from the blog

All articles