Skip to main content

Command Palette

Search for a command to run...

Drupal 8 module development #3 – adding a settings page

Published
•4 min read•View as Markdown
Drupal 8 module development #3 – adding a settings page
L

Known for his open source and JavaScript security initiatives, Liran Tal is an award-winning software developer, security researcher, and open source champion in the JavaScript community. He's an internationally recognized GitHub Star, acknowledged for his open source advocacy, and has received the OpenJS Foundation's Pathfinder for Security for his work on Node.js security. His contributions to developer security education include leading OWASP projects, building supply chain security tools, participation in CNCF and OpenSSF initiatives, and authoring books such as O'Reilly's Serverless Security. He leads the developer advocacy team at Snyk.io and is on a mission to empower developers with better application security skills.

Sep 25, 2013 ~ 4 min read

Drupal 8 module development #3 – adding a settings page

share this story on

You need a module configuration page for your new Drupal 8 module and here is how to build one using GlobalredirectSettingsForm

Drupal modules often provide an administrator with a settings page so that various configuration options can be tuned and setup using the web interface. We will take a look at how we can create a configuration page and get to know some basic interactions with Drupal’s new configuration system.

In the previous article we briefly introduced the routing system, with adding a basic route. When that route is triggered Drupal will be searching for the settings form class implementation - Drupal\globalredirect\Form\GlobalredirectSettingsForm that we defined in the route setting.

Let’s begin by creating this directory structure of lib/Drupal/globalredirect/Form in the module’s root directory and then create the form class GlobalRedirectSettingsForm.php which will contain the skeleton class:

<?php /**

  • @file
  • This is the GlobalRedirect admin include which provides an interface to global redirect to change some of the default settings
  • Contains \Drupal\globalredirect\Form\GlobalredirectSettingsForm. */

    namespace Drupal\globalredirect\Form;

    use Drupal\system\SystemConfigFormBase; use Drupal\Core\Config\ConfigFactory; use Symfony\Component\DependencyInjection\ContainerInterface;

    /**

  • Defines a form to configure module settings. */ class GlobalredirectSettingsForm extends SystemConfigFormBase {

    /**

    • {@inheritdoc} */ public function getFormID() { return 'globalredirect_settings'; }

    }

A few things to point out about this class:

  1. It defines the namespace, per the directory structure the file resides in.
  2. It makes use of several classes we may need access to. In particular, ConfigFactory which provides access to Drupal’s configuration system so that we can get and save configuration items, and SystemConfigFormBase which is the base class for doing module’s settings form, basically replacing Drupal 7′s system_settings_form(). It extends on FormBase, the very basic form class which implements FormInterface.
  3. It implements getFormID() which returns a string, defining the form name.

Now that we have a very basic implementation of the module’s settings form we will need to implement some other methods which will get this form to actually display the form (to build the form if so to speak), handle submit actions, etc. Let’s proceed to update the form with some more code:

<?php /**

  • @file
  • This is the GlobalRedirect admin include which provides an interface to global redirect to change some of the default settings
  • Contains \Drupal\globalredirect\Form\GlobalredirectSettingsForm. */

    namespace Drupal\globalredirect\Form;

    use Drupal\system\SystemConfigFormBase; use Drupal\Core\Config\ConfigFactory; use Symfony\Component\DependencyInjection\ContainerInterface;

    /**

  • Defines a form to configure module settings. */ class GlobalredirectSettingsForm extends SystemConfigFormBase {

    /**

    • {@inheritdoc} */ public function getFormID() { return 'globalredirect_settings'; }

    /**

    • {@inheritdoc} */ public function buildForm(array $form, array &$form_state) {

      // Get all settings $config = $this->configFactory->get('globalredirect.settings'); $settings = $config->get();

      $form['settings'] = array( '#tree' => TRUE, );

      $form['settings']['deslash'] = array( '#type' => 'checkbox', '#title' => t('Deslash'), '#description' => t('If enabled, this option will remove the trailing slash from requests. This stops requests such as example.com/node/1/ failing to match the corresponding alias and can cause duplicate content. On the other hand, if you require certain requests to have a trailing slash, this feature can cause problems so may need to be disabled.'), '#default_value' => $settings['deslash'], );

      return parent::buildForm($form, $form_state); }

    /**

    • {@inheritdoc}
    • Compares the submitted settings to the defaults and unsets any that are equal. This was we only store overrides. */ public function submitForm(array &$form, array &$form_state) {

      // Get config factory $config = $this->configFactory->get('globalredirect.settings');

      $form_values = $form_state['values']['settings'];

      $config ->set('deslash', $form_values['deslash']) ->save();

      parent::submitForm($form, $form_state);

    }

    }

The updated class has now implementations for buildForm() and submitForm(). The code shows only how the deslash configuration property is configured to avoid pasting a very large chunk of code with all the settings this module actually configures.

While the ConfigFactory and ContainerInterface classes aren’t really required explicitly, if you’re wondering what is their purpose then you should consult the class source of SystemConfigFormBase, which implements the required methods for dependency injection. What does that mean? To explain roughly, the class makes use of constructor injection principle to make some objects available for you “behind the scenes”. This eliminates cluttered code and allows for more reusable code. If you’re asking yourself where is the configFactory coming from in our class? the answer is dependency injection. We could’ve used the global config() function or possibly the static Drupal::Config() method but we didn’t, because using the configFactory is a more preferred method.

More from this blog

Liran Tal's blog

178 posts

Author of Node.js Secure Coding, Awarded GitHub Star and OpenJS Foundation's Pathfinder Award for Security. Security researcher, advocate for open source, web security and kindness.