How to add a settings page in your custom WordPress plugin

Most of the WordPress Plugins have their own configuration or options page to manage the different settings pertaining to the plugin. For example, Woocommerce- one of the most popular e-commerce plugins has a settings page to manage its settings for payment gateways, shipping, etc.

In this tutorial, I am going to explain how to add a settings page for your custom plugin in 4 simple steps:

  1. Add action hook for the tag ‘admin_menu’ & ‘admin_init’.
  2. Define the callback functions.
  3. Call add_submenu_page or add_options_page depending upon whether you would like to appear the settings submenu under your plugin or Settings main menu.
  4. Define the callback functions to render the heading & fields.

Let’s go through each step in detail.

Step 1:

The very first thing you should be doing is add a couple of action hooks.

add_action( 'admin_init', 'settings_init' );
add_action( 'admin_menu', 'add_settings_menu' );

If your plugin is built using classes, you need to use the array callable syntax. You would pass the function to add_action() as an array, with $this as the first element, then the name of the class method, like so:

add_action( 'admin_init', $plugin_admin, array($this, 'settings_init' ) );
add_action( 'admin_menu', $plugin_admin, array($this, 'add_settings_menu' ) );

If the class is called statically or extended, we would use the following approach to add the action hook:

add_action( 'admin_init', array( get_called_class(), 'settings_init' ) );
add_action( 'admin_menu', array( get_called_class(), 'add_settings_menu' ) );

Step 2:

In this step we would define the callback function that will call the required method to generate the submenu.

If you want to display the submenu in the Settings main menu, add the following code snippet:

/**
 * Sub menu
 */
public function options_page() {
	 add_options_page(
		 __( 'WPB Example', 'wpb-example'),
		 __( 'WPB Settings', 'wpb-example'),
		 'manage_options',
		 'wpb-settings',
		 array($this, 'settings_page_html')
	 );
}

More details about the add_options_page method can be read at the official WordPress site.

Once the above code is added you can see a new menu option being added in the Settings main menu.

Wordpress Settings page.

If you need to add the settings submenu under your Plugin main menu, use the following code snippet:

/**
 * Sub menu
 */
public function options_page() {
	 add_submenu_page(
		'edit.php?post_type=wpb-example',
		 __( 'WPB Example', 'wpb-example'),
		 __( 'WPB Settings', 'wpb-example'),
		 'manage_options',
		 'wpb-settings',
		 array($this, 'settings_page_html')
	 );
}

The first parameter of the add_submenu_page method is the parent_slug, in our case it is wpb-example, which is a custom post type. If your custom post type is ‘test-gallery’, the first parameter would be:

'edit.php?post_type=test-gallery',

Assuming that the plugin is class based, the last parameter requires you to pass the callback method as an array, in this case settings_page_html is a callback method that would display the setting’s page output.

More details about the method can be found out at official WordPress site.

A new submenu would be added in the plugin’s parent menu.

Custom WordPress Plugin settings page.

Step 3:

The last step is to code the settings page with required fields, save the fields and fetch the values from the database to display them. In Step 2, we had passed a callback function settings_page_html, let’s define that function in this step.

/**
 * Displays the settings page 
 *
 * @since    1.0.0
 */
public function settings_page_html() {
	
	// Check user capabilities
	if ( ! current_user_can( 'manage_options' ) ) {
		return;
	}
	.
	// Register a settings error/ message to be displayed to the user.
	if ( isset( $_GET['settings-updated'] ) ) {
		add_settings_error( $this->plugin_name.'-messages', $this->plugin_name.'-message', __( 'Settings updated', $this->plugin_name ), 'updated' );
	}

	// Include the form to display the setting fields
	require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/partials/wpbred-examples-admin-settings.php';
}

In the above function, first of all, we are checking the capabilities of the logged-in user if the user is authorized to update the settings page.

The next line of code registers a settings error/ message to be displayed to the user.

Finally, we are including a partial file that has the form and fields in it.

<div class="wrap">
	<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
	<form action="options.php" method="post">
		 <?php
		 settings_fields( $this->plugin_name );
		 do_settings_sections( $this->plugin_name );
		 submit_button(__( 'Save Settings', $this->plugin_name),);
		 ?>
	</form>
</div>

Step 4:

In the last step, we will define the callback function settings_init. (In step 1, we had added an action hook, admin_init to call this method). admin_init is triggered before any other hook when a user accesses the admin area of WordPress.

In this method, we are going to perform three actions:

  1. Add a section heading to the settings page using the add_settings_section method.
  2. Add a field ( you can add as many fields as you want, you can also customize the HTML the way you would need to ), using add_settings_field method.
  3. Register the settings for our plugin using the register_setting method.
/**
 * Custom options & settings for the admin area.
 *
 * @since    1.0.0
 */
 public function settings_init() {
	
	$settingsId = $this->plugin_name.'-settings';
	
	// Add section heading
	add_settings_section(
		$settingsId, __( 'WP Bred Demo Settings', $this->plugin_name ), [$this, 'render_setting_heading'], $this->plugin_name
	);
	
	// Add Min width field
	add_settings_field(
		'image_min_width',
		__( 'Minimum Width', $this->plugin_name),
		[$this,'render_text_field'],
		$this->plugin_name,
		$settingsId,
		['id' => 'image_min_width', 'name' => 'image_min_width', 'placeholder' => __('Minimum width', $this->plugin_name), 'default_value' => '800', 'class' => 'form-field form-required', 'style' => 'width:15em']
	);

	// Add Max width field
	add_settings_field(
		'image_max_width',
		__( 'Maximum Width', $this->plugin_name),
		[$this,'render_text_field'],
		$this->plugin_name,
		$settingsId,
		['id' => 'image_max_width', 'name' => 'image_max_width', 'placeholder' => __('Maximum width', $this->plugin_name), 'default_value' => '1920', 'class' => 'form-field form-required', 'style' => 'width:15em']
	);

	// Register settings
	register_setting( $this->plugin_name, 'wpb_examples_options' );
}

Callback functions to render the heading & fields HTML are defined as below:

/**
 * Render section heading
 *
 * @since    1.0.0
 */
public function render_setting_heading( $args ) {
	?>
	<p id="<?php echo esc_attr( $args['id'] ); ?>">
		<?php esc_html_e( 'Ideal image dimension should be 1920x1080 px.', $this->plugin_name ); ?>
	</p>
	<?php
}

/**
 * Render a text field
 *
 * @since    1.0.0
 */
public function render_text_field( $args ) {
	$options = get_option( 'wpb_examples_options' );
	?>
	<input type="text" 
		id="<?php echo esc_attr( $args['id'] ); ?>" 
		name="wpb_examples_options[<?php echo esc_attr( $args['name'] ); ?>]" 
		value="<?php echo isset( $options[ $args['name'] ] ) ? $options[ $args['name'] ] : esc_attr( $args['default_value']); ?>" 
		class="<?php echo isset($args['class']) ? $args['class']: '' ?>" 
		style="<?php echo isset($args['style']) ? $args['style']: '' ?>" 
		placeholder="<?php echo esc_attr( $args['placeholder'] ); ?>"/>
	<?php
}

If you have carefully following the above instructions you would have a working settings page for your plugin.

Wordpress custom plugin settings page.

You can view the complete source code of this tutorial at Github or download the working example plugin:

Leave a Reply