I've expanded this, cleaned it up a bit and moved it to another repo.
Rational Option Page Class is a PHP class used to build option pages for WordPress. You don't need to deal with all the hooks and functions. What you pass to this class is an associative array with your option page's structure and fields.
- Download or clone the repo to your plugin or theme's root directory
- Include the class in your plugin's base file or your theme's
functions.php
file.
if ( is_admin() ) {
include 'rational-option-page/class.rational-option-page.php';
$my_options_page = new RationalOptionPages();
}
I recommend using underscores as separators in all your slugs and IDs to keep it consistent. I haven't tested it extensively with hyphens. But they might work.
The class builds your option page based off of a multidimensional associative array that you define. To get your top level page set up you would use something like this:
$my_options_page_structure = array(
// top level
array(
'page_title' => 'My Options Page',
'menu_title' => 'My Options Page',
'capability' => 'manage_options',
'menu_slug' => 'my_options_page',
'icon_url' => 'dashicons-editor-code',
'position' => 61,
),
);
$my_options_page->pages( $my_options_page_structure );
The above example defines the top level page, "My Options Page". It also sets an icon and positions it where I want it in the admin menu. It uses WordPress' add_menu_page
to do this. You can add multiple pages via the same instance of the class by adding more arrays at the root level of the array passed to the pages()
method.
For instance a second, top-level menu page could be added like so:
$my_options_page_structure = array(
// top level
array(
'page_title' => 'My Options Page',
'menu_title' => 'My Options Page',
'capability' => 'manage_options',
'menu_slug' => 'my_options_page',
'icon_url' => 'dashicons-editor-code',
'position' => 61,
),
// a second top level
array(
'page_title' => 'Another Page',
'menu_title' => 'Another Page',
'capability' => 'manage_options',
'menu_slug' => 'another_page',
),
);
$my_options_page->pages( $my_options_page_structure );
- More
icon_url
options: http://melchoyce.github.io/dashicons/ - More on
position
: https://codex.wordpress.org/Function_Reference/add_menu_page#Parameters
Subpages are defined within a "subpages" array inside the top level page. If we extend the above example:
$my_options_page_structure = array(
// top level
array(
'page_title' => 'My Options Page',
'menu_title' => 'My Options Page',
'capability' => 'manage_options',
'menu_slug' => 'my_options_page',
'icon_url' => 'dashicons-editor-code',
'position' => 61,
'subpages' => array(
array(
'page_title' => 'My Options Subpage',
'menu_title' => 'My Options Subpage',
'capability' => 'manage_options',
'menu_slug' => 'my_options_subpage',
),
),
),
);
The above example defines the subpage "My Options Subpage" of the parent "My Options Page". This is done using WordPress' add_submenu_page
function.
As with pages, you can add multiple subpages under one page by including another array after the first:
$my_options_page_structure = array(
// top level
array(
'page_title' => 'My Options Page',
'menu_title' => 'My Options Page',
'capability' => 'manage_options',
'menu_slug' => 'my_options_page',
'icon_url' => 'dashicons-editor-code',
'position' => 61,
'subpages' => array(
// subpage one
array(
'page_title' => 'My Options Subpage',
'menu_title' => 'My Options Subpage',
'capability' => 'manage_options',
'menu_slug' => 'my_options_subpage',
),
// subpage two
array(
'page_title' => 'My Second Subpage',
'menu_title' => 'My Second Subpage',
'capability' => 'manage_options',
'menu_slug' => 'my_second_subpage',
),
),
),
);
- WordPress'
add_submenu_page
function: https://codex.wordpress.org/Function_Reference/add_submenu_page
Any page, page or subpage, can contain sections and fields. These are defined first by section arrays within that page or subpage's array. Again, expanding on the examples above:
$my_options_page_structure = array(
// top level
array(
'page_title' => 'My Options Page',
'menu_title' => 'My Options Page',
'capability' => 'manage_options',
'menu_slug' => 'my_options_page',
'icon_url' => 'dashicons-editor-code',
'position' => 61,
'sections' => array(
array(
'id' => 'page_section',
'title' => 'Page Section',
),
),
'subpages' => array(
array(
'page_title' => 'My Options Subpage',
'menu_title' => 'My Options Subpage',
'capability' => 'manage_options',
'menu_slug' => 'my_options_subpage',
'sections' => array(
array(
'id' => 'subpage_section',
'title' => 'Subpage Section',
),
),
),
),
),
);
The above example adds sections to both the main page and the subpage. These sections are necessary as they will contain the fields. You can have multiple sections on one page by adding multiple arrays to the sections
array. In much the same way you can create multiple pages and subpages within their respective arrays.
Based on WordPress' add_settings_section
: https://codex.wordpress.org/Function_Reference/add_settings_section
Fields are nested under the sections of our pages. You can have as many as you like, in the same way as with sections and pages, but the sections and pages should be utilized to keep them organized.
$my_options_page_structure = array(
// top level
array(
'page_title' => 'My Options Page',
'menu_title' => 'My Options Page',
'capability' => 'manage_options',
'menu_slug' => 'my_options_page',
'icon_url' => 'dashicons-editor-code',
'position' => 61,
'sections' => array(
array(
'id' => 'page_section',
'title' => 'Page Section',
'fields' => array(
// text input
array(
'id' => 'sample_text',
'title' => 'Sample Text',
'type' => 'text',
),
),
),
),
),
);
The above example creates a text input field, in the page section, on the top level page of our options.
Based on WordPress' add_settings_field
: https://codex.wordpress.org/Function_Reference/add_settings_field
page_title
: The text to be displayed in the title tags of the page when the menu is selected (required)menu_title
: The on-screen name text for the menu (required)capability
: The capability required for this menu to be displayed to the user (required)menu_slug
: The slug name to refer to this menu by (should be unique for this menu) (required)icon_url
: The icon for this menuposition
: The position in the menu order this menu should appearsubpages
: Array of pages to appear under this onesections
: Array of sections to appear on this page
Same as above but icon_url
, position
and subpages
will be ignored.
id
: String for use in the 'id' attribute of tags (required)title
: Title of the section (required)description
: HTML/Text to appear under the section's titlefields
: Array of fields to appear in this section
There are a few options that are required for all fields:
id
: String used for field's ID and name (required)title
: String used for field label (required)type
: Determines what type of field is created (required)
Individual field types also have options specific to them. Some required:
class
: Class applied to the text field (default:regular-text
)value
: Default value if no value stored in the databasepattern
: Specifies a regular expression the field value is checked againstplaceholder
: HTML5 placeholder attributesize
: Specifies the visible width, in characters, of the fieldmaxlength
: Specifies the maximum number of characters allowed in the fielddescription
: Used as "help text" for the fieldargs
: An array of true/false arguments for the fieldrequired
autocomplete
readonly
disabled
multiple
(email only)
class
: Class applied to the text field (default:regular-text
)value
: Default value if no value stored in the databasemin
: Specifies the minimum value for the fieldmax
: Specifies the maximum value for the fieldstep
: Specifies the legal number intervals for the fielddescription
: Used as "help text" for the fieldargs
: An array of true/false arguments for the fieldrequired
autocomplete
readonly
disabled
class
: Class applied to the text field (default:regular-text
)value
: Default value if no value stored in the databaseplaceholder
: HTML5 placeholder attributerows
: Specifies the visible height of a text area, in linescols
: Specifies the visible width of a text areadescription
: Used as "help text" for the fieldargs
: An array of true/false arguments for the fieldrequired
autocomplete
readonly
disabled
class
: Class applied to the text field (default for number:regular-text
)value
: Default value if no value stored in the databasemin
: Specifies the minimum value for the fieldmax
: Specifies the maximum value for the fieldstep
: Specifies the legal number intervals for the fielddescription
: Used as "help text" for the fieldargs
: An array of true/false arguments for the fielddisabled
class
: Class applied to the text fieldvalue
: Default value if no value stored in the databasedescription
: Used as "help text" for the fieldargs
: An array of true/false arguments for the fielddisabled
class
: Class applied to the text fieldvalue
: Default value if no value stored in the databasedescription
: Used as "help text" for the fieldargs
: An array of true/false arguments for the fieldrequired
disabled
class
: Class applied to the text fieldvalue
: Default value if no value stored in the databasedescription
: Used as a label for the fieldargs
: An array of true/false arguments for the fieldrequired
disabled
options
: (required) Array of choices/options (Example below)class
: Class applied to the text fieldvalue
: Default value if no value stored in the databaseargs
: An array of true/false arguments for the fielddisabled
Sequential or associative arrays work for the options array.
'options' => array(
'Option One',
'option-two' => 'Option Two',
)
The above array would result in something like this:
<label><input type="radio" name="my_radio" value="Option One"> Option One</label><br>
<label><input type="radio" name="my_radio" value="option-two"> Option Two</label>
Notice that the key in the associative part of the array is used as the value of the input.
options
: (required) Array of choices/options (Example below)class
: Class applied to the text fieldvalue
: Default value if no value stored in the databasedescription
: Used as "help text" for the fieldargs
: An array of true/false arguments for the fielddisabled
Options in selects behave in the same way as in the radio fields but with a slightly different output. The array above would render something like this:
<option>Option One</option>
<option value="option-two">Option Two</option>
This is a page array with one section and one of each category of field:
$pages = array(
// page
array(
'page_title' => 'My Options',
'menu_title' => 'My Options',
'capability' => 'manage_options',
'menu_slug' => 'my_options',
'description' => '<p>Some options for my theme.</p>',
// subpage
'sections' => array(
array(
'id' => 'sample_fields',
'title' => 'Sample Fields',
'description' => '<p>Sample fields supported by the class</p>',
'fields' => array(
array(
'id' => 'sample_text',
'title' => 'Sample Text',
'type' => 'text',
'description' => 'Things like text, search, url, tel, email and password.',
'value' => 'Default value',
),
array(
'id' => 'sample_textarea',
'title' => 'Sample Textarea',
'type' => 'textarea',
'value' => 'Defaults to a large, code-style block but can easily be changed with class, rows and cols.',
),
array(
'id' => 'sample_checkbox',
'title' => 'Sample Checkbox',
'type' => 'checkbox',
'description' => 'Checkboxes of course.',
),
array(
'id' => 'sample_radio',
'title' => 'Sample Radio',
'type' => 'radio',
'options' => array(
'Radio options are similar to those for selects',
'radio-two' => 'Sequential or associative arrays work',
),
),
array(
'id' => 'sample_select',
'title' => 'Sample Select',
'type' => 'select',
'options' => array(
'Radio options are similar to those for selects',
'radio-two' => 'Sequential or associative arrays work',
),
'description' => 'See? Same as the radio input above.'
),
array(
'id' => 'sample_file',
'title' => 'Sample File',
'type' => 'file',
'description' => 'Included file uploads for fun.'
),
),
),
),
),
);
Try passing this array to the class and see what it generates.
The data is stored like all other options in the wp_options
table. It can be retrieved using the get_option()
function and passing the menu_slug
of the page where the field(s) are located with an underscore prepended and the string _options
appended. For example, if your page's menu slug is sample_page
you would retrieve the values by calling get_option( '_sample_page_options' )
. This will return an array with your stored values. Read more: https://codex.wordpress.org/Function_Reference/get_option