In this tutorial, we will learn how to add a network settings page for your WordPress theme or plugin, add settings fields to this page, and update these fields.

Add network settings page – register menu

If you haven’t already added settings page for your WordPress theme or plugin in a regular non-multisite install, there are different hooks you can use but the proper one isĀ admin_menu, now for a network you’ll notice that WordPress prefixes most of these hooks with network_ in the beginning and so we will be after network_admin_menu hook to register our page with add_submenu_page function.

Since the title says “settings”, we will be adding our page to settings menu, which has file of settings.php, but you can always add to different parent menus such as sites.php, tools.php, etc. Here’s some class to get us started:

<?php namespace MyPlugin\Admin;

class Admin
{

    /**
      * This method will be used to register
      * our custom settings admin page
      */

    public function init()
    {
        add_action('network_admin_menu', array($this, 'setupTabs'));
    }

    /**
      * This method will be used to register
      * our custom settings admin page
      */

    public function setupTabs()
    {
        \add_submenu_page(
            'settings.php',
            'My Plugin Settings',
            'My Plugin',
            'manage_options',
            'my-plugin',
            array($this, 'screen')
        );

        return $this;
    }

    /**
      * This method will parse the contents of
      * our custom settings age
      */

    public function screen()
    {
        printf('Hello from %s::%s!', __CLASS__, __FUNCTION__);
    }
}

$MyPluginAdmin = new \MyPlugin\Admin\Admin;
$MyPluginAdmin->init();

Great! Now if you properly place the above class declaration code into a file and call it, it will register us the custom network admin settings page, which will print out some basic dummy text.

Add network settings page – parse content

From this step we will be after parsing the settings contents and fields to our custom settings page. Now as if you don’t know there is a handy tool for registering and processing custom settings in the WordPress plugin API, but I’ll do this tutorial in the boring way which will consist of basically 1 or 2 fields processed with native PHP and of course WordPress API.

Now that you’re determined to put together couple settings for your admin settings page, it should make sense that these settings should be global (the same on all over the network) since the plugin is network-wide active, unlike when it is active for a given blog where you probably want the settings to be saved just to that blog instance. Therefore, we will be using update_site_option and get_site_option to process/get our settings, which will save the settings to the network meta and therefore they will be global.

Add network settings page – wrap up

Follows the wrap-up of our basic class code used to make 2 example fields of settings, update them and get their settings.

<?php namespace MyPlugin\Admin;

class Admin
{
    public $updated;
    /**
      * This method will be used to register
      * our custom settings admin page
      */

    public function init()
    {
        // register page
        add_action('network_admin_menu', array($this, 'setupTabs'));
        // update settings
        add_action('network_admin_menu', array($this, 'update'));
    }

    /**
      * This method will be used to register
      * our custom settings admin page
      */

    public function setupTabs()
    {
        \add_submenu_page(
            'settings.php',
            __('My Plugin Settings', 'my-plugin-domain'),
            __('My Plugin'),
            'manage_options',
            'my-plugin',
            array($this, 'screen')
        );

        return $this;
    }

    /**
      * This method will parse the contents of
      * our custom settings age
      */

    public function screen()
    {
        ?>

        <div class="wrap">

            <h2><?php _e('My Plugin Admin', 'my-plugin-domain'); ?></h2>

            <?php if ( $this->updated ) : ?>
                <div class="updated notice is-dismissible">
                    <p><?php _e('Settings updated successfully!', 'my-plugin-domain'); ?></p>
                </div>
            <?php endif; ?>

            <form method="post">

                <p>
                    <label>
                        <?php _e('Enter your email address below:', 'my-plugin-domain'); ?>
                        <br/>
                        <input type="email" name="email" value="<?php echo esc_attr($this->getSettings('email')); ?>" size="50" />
                    </label>
                </p>

                <p>
                    <label>
                        <?php _e('Select your age range:', 'my-plugin-domain'); ?>
                        <br/>
                        <select name="age_range">
                            <option value="" <?php selected($this->getSettings('age_range'), null); ?>><?php _e('Select Range', 'my-plugin-domain'); ?></option>
                            <?php foreach ( array('13-18', '18-26', '26-40', '40-60') as $range ) : ?>
                                <option value="<?php echo esc_attr($range); ?>" <?php selected($this->getSettings('age_range'), $range); ?>><?php echo esc_attr($range); ?></option>
                            <?php endforeach; ?>
                        </select>
                    </label>
                </p>

                <?php wp_nonce_field('my_plugin_nonce', 'my_plugin_nonce'); ?>
                <?php submit_button(); ?>

            </form>

        </div>

        <?php
    }

    /**
      * Check for POST (form submission)
      * Verifies nonce first then calls
      * updateSettings method to update.
      */

    public function update()
    {
        if ( isset($_POST['submit']) ) {
            
            // verify authentication (nonce)
            if ( !isset( $_POST['my_plugin_nonce'] ) )
                return;

            // verify authentication (nonce)
            if ( !wp_verify_nonce($_POST['my_plugin_nonce'], 'my_plugin_nonce') )
                return;

            return $this->updateSettings();
        }
    }

    /**
      * Updates settings
      */

    public function updateSettings()
    {
        $settings = array();

        if ( isset($_POST['email']) && is_email($_POST['email']) ) {
            $settings['email'] = esc_attr($_POST['email']);
        }

        if ( isset($_POST['age_range']) && trim($_POST['age_range']) ) {
            $settings['age_range'] = sanitize_text_field($_POST['age_range']);
        }

        if ( $settings ) {
            // update new settings
            update_site_option('my_plugin_settings', $settings);
        } else {
            // empty settings, revert back to default
            delete_site_option('my_plugin_settings');
        }

        $this->updated = true;
    }

    /**
      * Updates settings
      *
      * @param $setting string optional setting name
      */

    public function getSettings($setting='')
    {
        global $my_plugin_settings;

        if ( isset($my_plugin_settings) ) {
            if ( $setting ) {
                return isset($my_plugin_settings[$setting]) ? $my_plugin_settings[$setting] : null;
            }
            return $my_plugin_settings;
        }

        $my_plugin_settings = wp_parse_args(get_site_option('my_plugin_settings'), array(
            'email' => null,
            'age_range' => null
        ));

        if ( $setting ) {
            return isset($my_plugin_settings[$setting]) ? $my_plugin_settings[$setting] : null;
        }
        return $my_plugin_settings;
    }
}

$MyPluginAdmin = new \MyPlugin\Admin\Admin;
$MyPluginAdmin->init();

Here’s a screenshot also:

Add WordPress network settings page for your plugin

Digital Ocean

Cheap Cloud SSD Hosting

Get a VPS now starting at $5/m, fast and perfect for WordPress and PHP applications

Sign Up with $10 Credit