# Creating Custom Options Pages

## Creating Custom Options Pages

1. [Blog](https://rudrastyh.com/)&#x20;
2. [WordPress](https://rudrastyh.com/wordpress)
3. [Create an Admin Page](https://rudrastyh.com/wordpress/creating-options-pages.html#create-admin-pages)
4. [Add Fields](https://rudrastyh.com/wordpress/creating-options-pages.html#add-fields)
5. [Easy Example](https://rudrastyh.com/wordpress/creating-options-pages.html#example)

First of all please check the screenshot, it is what we are going to create in this tutorial:![WordPress settings page with input field](https://rudrastyh.com/wp-content/uploads/2020/07/wordpress-settings-page-with-input-field.gif)

### 1. Create an Admin Page <a href="#create-admin-pages" id="create-admin-pages"></a>

The first step for us is to decide where exactly in admin menu we are going to create an option page.![WordPress admin menu](https://rudrastyh.com/wp-content/uploads/2020/07/wordpress-admin-menu.png)The good news – you can create it anywhere, whether it is in the Settings section, Dashboard section or a new custom section with an icon.

There are primarily two functions for that:

* `add_menu_page()` – to create a new top-level menu page,
* `add_submenu_page()` – to create a submenu page.

To simplify the process, instead of `add_submenu_page()` you can use `add_dashboard_page()`, `add_posts_page()`, `add_pages_page()`, `add_comments_page()`, `add_theme_page()`, `add_plugins_page()`, `add_users_page()`, `add_management_page()` or `add_options_page()` depending on where you’re going to add your submenu page.

Okay, let’s dive into the examples.

#### Create a custom top-level menu page

Take a look at this code:

```
add_action( 'admin_menu', 'misha_menu_page' );
 
function misha_menu_page() {
 
	add_menu_page(
		'My Page Title', // page <title>Title</title>
		'My Page', // menu link text
		'manage_options', // capability to access the page
		'misha-slug', // page URL slug
		'misha_page_content', // callback function /w content
		'dashicons-star-half', // menu icon
		5 // priority
	);
 
}
 
function misha_page_content(){
 
	echo 'What is up?';
 
}
```

It is super simple, but if you insert it to your `functions.php` file, a new admin page will appear.![Custom menu page in WordPress admin area](https://rudrastyh.com/wp-content/uploads/2020/07/wordpress-custom-menu-page.png)

If you don’t understand how I have added an icon there, just check the [Dashicons](https://developer.wordpress.org/resource/dashicons/#star-half) icon set.

#### Create a custom options page

Creating a new menu item with an icon is cool but the truth is when you create a plugin settings page, it is always better to add it as a submenu page under **Settings.**

It is the best practice and in most cases I recommend you to do it that way.

```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
```

```
add_action( 'admin_menu', 'misha_options_page' );
 
function misha_options_page() {
 
	add_options_page(
		'My Page Title', // page <title>Title</title>
		'My Page', // menu link text
		'manage_options', // capability to access the page
		'misha-slug', // page URL slug
		'misha_page_content', // callback function with content
		2 // priority
	);
 
}
 
function misha_page_content(){
 
	echo 'What is up?';
 
}
```

Very similar to the previous example, isn’t it? We only don’t have an icon parameter anymore.![How to create an options page in WordPress](https://rudrastyh.com/wp-content/uploads/2020/07/wordpress-create-options-page.png)

Now you already know how to add any custom HTML to your options pages, but in the next chapter I will show you how to properly create settings fields there.

### 2. Add Fields with Settings API <a href="#add-fields" id="add-fields"></a>

First of all let’s populate our `misha_page_content()` function which we created in the previous step.

```
1
2
3
4
5
6
7
8
9
10
11
12
13
```

```
function misha_page_content(){
 
	echo '<div class="wrap">
	<h1>My Page Settings</h1>
	<form method="post" action="options.php">';
 
		settings_fields( 'misha_settings' ); // settings group name
		do_settings_sections( 'misha-slug' ); // just a page slug
		submit_button();
 
	echo '</form></div>';
 
}
```

We are not going to make any changes in this functions anymore. All you have to know is that we use two functions `settings_fields()` and `do_settings_sections()` to print all the settings fields and to populate them with data.

If you did everything correctly until this moment, you will have this:![WordPress options page without fields](https://rudrastyh.com/wp-content/uploads/2020/07/settings-page-with-no-fields.png)

#### 2.1 Register a setting and create a field

```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
```

```
add_action( 'admin_init',  'misha_register_setting' );
 
function misha_register_setting(){
 
	register_setting(
		'misha_settings', // settings group name
		'homepage_text', // option name
		'sanitize_text_field' // sanitization function
	);
 
	add_settings_section(
		'some_settings_section_id', // section ID
		'', // title (if needed)
		'', // callback function (if needed)
		'misha-slug' // page slug
	);
 
	add_settings_field(
		'homepage_text',
		'Homepage text',
		'misha_text_field_html', // function which prints the field
		'misha-slug', // page slug
		'some_settings_section_id', // section ID
		array( 
			'label_for' => 'homepage_text',
			'class' => 'misha-class', // for <tr> element
		)
	);
 
}
 
function misha_text_field_html(){
 
	$text = get_option( 'homepage_text' );
 
	printf(
		'<input type="text" id="homepage_text" name="homepage_text" value="%s" />',
		esc_attr( $text )
	);
 
}
```

What is `esc_attr()` function and why it is here? There is [a separate tutorial](https://rudrastyh.com/wordpress/escaping-outputs.html) on my blog about escaping outputs where I said that database is not a trusted source of data and that’s why we must use escaping functions before we output anything into the page content.

And now we have a working options page:![WordPress settings page with input field](https://rudrastyh.com/wp-content/uploads/2020/07/wordpress-settings-page-with-input-field.gif)

#### 2.2 Sanitization

Let’s come back for a moment to a `register_setting()` function from the previous piece of code.

```
register_setting(
	'misha_settings',
	'homepage_text',
	'sanitize_text_field' // sanitization function
);
```

The third parameter is the function name which is intended to sanitize (clean) the field data before saving into the database. For example `sanitize_text_field()` is the default WordPress function that removes all the characters that are not allowed in use in an input text field. If you would like to to pass an integer, you can use `intval()` or `absint()` function names instead. Or create a custom sanitization function for your purpose.

Example for positive integers:

```
register_setting( 'misha_settings', 'number_of_slides', 'absint' );
```

### 3. Easy example <a href="#example" id="example"></a>

We have some code above. Actually a lot of code. And it is all about to create a single input field.

I want to be honest with you – I never do all that manually on my projects. Because it is so time consuming. What is the solutions then? I also don’t like plugins, especially ACF-like ones. Because I’d better spend a couple more hours and create a fast website instead of using slow bloated plugins.

Finally I came to a solution – I created [my own option pages plugin](https://rudrastyh.com/plugins/meta-boxes-options-pages) with the bare minimum of the functionality. It is lightning fast just like you code everything in `functions.php`, but at the same time it saves hours of development.

Just compare this code to everything we did above:

```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
```

```
add_filter( 'simple_register_option_pages', 'misha_option_page' );
 
function misha_option_page( $option_pages ) {
 
	$option_pages[] = array(
		'id'	=> 'misha_slug',
		'title' => 'My Page Settings',
		'menu_name' => 'My page',
		'fields' => array(
			array(
				'id' => 'homepage_text',
				'label' => 'Homepage text',
				'type' => 'text',
			),
 		),
	);
 
	return $option_pages;
 
}
```

And we have absolutely the same result as we have creating an option page from scratch in the first part of the tutorial.![WordPress settings page with input field](https://rudrastyh.com/wp-content/uploads/2020/07/wordpress-settings-page-with-input-field.gif)

#### Related tutorials

* [Plugin to Create Option Pages on the fly](https://rudrastyh.com/plugins/meta-boxes-options-pages)
* [Custom Media Uploader in WordPress admin](https://rudrastyh.com/wordpress/customizable-media-uploader.html)
