Dorokhov.codes

04. Administration Menus

Adding a page to a top-level menu

A menu item and a page are registered together using the add_menu_page() function.

add_menu_page(
    string $page_title,         // The text to be displayed in the title tags of the page when the menu is selected.
    string $menu_title,         // The text to be used for the menu.
    string $capability,         // The capability required for this menu to be displayed to the user.
    string $menu_slug,          // The slug name to refer to this menu by.
    callable $callback = '',    // The function to be called to output the content for this page.
    string $icon_url = '',      // The URL to the icon to be used for this menu (or a CSS-class).
    int|float $position = null  // The position in the menu order this item should appear.
);

We should add pages during the admin_menu action hook:

add_action( 'admin_menu', 'add_admin_menu' );

function add_admin_menu() {
    add_menu_page();
}

Before showing HTML we must check capabilities:

// Check user capabilities:
if ( ! current_user_can( 'manage_options' ) ) {
    return;
}

Showing the HTML:

<div class="wrap">
    <h1><?= esc_html( get_admin_page_title() ); ?></h1>
    <form action="options.php" method="post">
        <?php
        // output security fields for the registered setting "wporg_options"
        settings_fields('wporg_options');
        // output setting sections and their fields
        // (sections are registered for "wporg", each field is registered to a specific section)
        do_settings_sections('wporg');
        // output save settings button
        submit_button('Save Settings');
        ?>
    </form>
</div>

WordPress recommends wrapping your HTML using a <div> with the wrap class.

The best practice for portable code would be to create a Callback that requires/includes your PHP file.

Parameters

$menu_slug examples:

// Just a menu slug. If we set it, we should set also a callback.
// It will give the URL like: /admin.php?page=plugin-settings
'plugin-settings'

// File to show (instead of using a callback function) - not a best practice:
plugin_dir_path( __FILE__ ) . 'admin/view.php',

$callback examples:

// Function:
'some_function'

// Class method:
[ $this, 'some_method' ]

// Class static method:
[ 'SomeClass', 'some_method' ]

// Path to the file:
plugin_dir_path( __FILE__ ) . 'admin/view.php'

$icon_url examples:

// URL to an icon:
plugin_dir_url( __FILE__ ) . 'images/icon.png'

// Dashicons: https://developer.wordpress.org/resource/dashicons/
'dashicons-admin-plugins'                      

$position examples:

// We can choose a position from the next list:
2 – Dashboard
4 – Separator
5 – Posts
10 – Media
15 – Links
20 – Pages
25 – Comments
59 – Separator
60 – Appearance
65 – Plugins
70 – Users
75 – Tools
80 – Settings
99 – Separator

Adding a page to a sub-level menu

To add a new Sub-menu to WordPress Administration, use the add_submenu_page() function.

add_submenu_page( 
    string $parent_slug,        // The slug name for the parent menu (or the file name of a standard WordPress admin page).
    string $page_title,         // The text to be displayed in the title tags of the page when the menu is selected.
    string $menu_title,         // The text to be used for the menu.
    string $capability,         // The capability required for this menu to be displayed to the user.
    string $menu_slug,          // The slug name to refer to this menu by.
    callable $callback = '',    // The function to be called to output the content for this page.
    int|float $position = null  // The position in the menu order this item should appear.
);

Parameters

$parent_slug examples:

Dashboard:          ‘index.php’
Posts:              ‘edit.php’
Media:              ‘upload.php’
Pages:              ‘edit.php?post_type=page’
Comments:           ‘edit-comments.php’
Custom Post Types:  ‘edit.php?post_type=your_post_type’
Appearance:         ‘themes.php’
Plugins:            ‘plugins.php’
Users:              ‘users.php’
Tools:              ‘tools.php’
Settings:           ‘options-general.php’
Network Settings:   ‘settings.php’

Predefined functions for sub-menus

Wouldn’t it be nice if we had helper functions that define the $parent_slug for WordPress built-in Top-level menus and save us from manually searching it through the source code?

add_dashboard_page() – index.php
add_posts_page() – edit.php
add_media_page() – upload.php
add_pages_page() – edit.php?post_type=page
add_comments_page() – edit-comments.php
add_theme_page() – themes.php
add_plugins_page() – plugins.php
add_users_page() – users.php
add_management_page() – tools.php
add_options_page() – options-general.php
add_options_page() – settings.php
add_links_page() – link-manager.php – requires a plugin since WP 3.5+
Custom Post Type – edit.php?post_type=wporg_post_type

Highlight sub item when click the main menu item

To achieve this behavior we need to do two things: make the menu-slug and callback the same as the main menu item.