Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough

Create a config form in Drupal 8

Parent Feed: 

In Drupal 7, to manage system variables, we used variable_get() / variable_set() /  variable_del() calls and stored those variables in the variable table of the database.

In Drupal 8 we now use the Configuration system which provides a central place for modules to store configuration data. This system allows to store information that can be synchronized between development and production sites. This information is often created during site building and is not typically generated by regular users during normal site operation.
In Drupal 8 configuration is still stored in the database,  but it can now be synced with YML files on the disk for deployment purposes aswell.

In this post we will create a configuration form that stores a configuration value in our system. In this case it will be a form that stores the value of an external API key. Next, we will retrieve this value and use it in a very simple controller.

1. Create the module
2. Create the form
3. Check the form
4. Retrieve the config information in a controller

1. Create the module skeleton

We use the following Drupal Console command.

drupal generate:module  \
--module="ex08" \
--machine-name="ex08" \
--module-path="modules/custom" \
--description="An simple example of a config form" \
--core="8.x" \
--package="Custom" \
--module-file \
--uri="http://default" \
--no-interaction

2. Create the form

To create the config form we use Drupal Console with the drupal generate:form:config command.

drupal generate:form:config  \
--module="ex08" \
--class="ExternalApiKeyForm" \
--form-id="external_api_key_form" \
--config-file \
--inputs='"name":"your_external_api_key", "type":"textfield", "label":"Your external API Key", "options":"", "description":"Enter your external API Key", "maxlength":"64", "size":"64", "default_value":"none", "weight":"0", "fieldset":""' \
--path="/admin/config/ex08/externalapikey" \
--uri="http://default" \
--no-interaction

This Drupal Console command will:
- create the config form file ExternalApiKeyForm.php under the src/form folder
- update or create the ex08.routing.yml file with a route to the config form to access it.

Now let’s see what this code is doing in detail.

3. The config form

If we now open the ExternalApiKeyForm.php file we see the following code.

config('ex08.externalapikey');
    $form['your_external_api_key'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Your external API Key'),
      '#description' => $this->t('Store the external API Key'),
      '#maxlength' => 64,
      '#size' => 64,
      '#default_value' => $config->get('your_external_api_key'),
    ];
    return parent::buildForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    parent::validateForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    parent::submitForm($form, $form_state);

    $this->config('ex08.externalapikey')
      ->set('your_external_api_key', $form_state->getValue('your_external_api_key'))
      ->save();
  }

}

Fist we see that the class ExternalApiKeyForm extends ConfigFormBase abstract class which also extends the FormBase abstract class.

The ExternalApiKeyForm class has four basic methods:

getEditableConfigNames() - gets the configuration object name (The name of the configuration environment where we store or get the values). In our case we give it the name: 'ex08'.externalapikey'.

getFormId() - returns the form's unique ID. This will be the name of our form or its ID. In our case, we named it 'external_api_key_form'.

buildForm() - returns the form array. This method creates the form and in this case one item named 'your_external_api_key'. This item is a text field. We will also use this name for
the key of the key/value pair stored in the configuration.

We also get the current value for the key 'your_external_api_key' from the configuration object to set it as a default value for this field:   '#default_value' => $config->get('your_external_api_key'),
 
validateForm() - validates the form.

submitForm() - processes the form submission. In this step, we will set and save the value of the key 'your_external_api_key' in the configuration system.

4. The route to the form

Drupal Console also updates or creates the ex08.routing.yml file with a route to the config form to access it.

ex08.external_api_key_form:
  path: '/admin/config/ex08/externalapikey'
  defaults:
    _form: '\Drupal\ex08\Form\ExternalApiKeyForm'
    _title: 'ExternalApiKeyForm'
  requirements:
    _permission: 'access administration pages'
  options:
    _admin_route: TRUE

Nothing strange here. With path we define the URL to access the form. With _form we indicate the class which generates the form and with _title we define the title of the form.  With _permission we give access to users who have permission to access administration pages (user access to the administration path).

Now that we have a form and a route, we can access the form from the URL /admin/config/ex08/externalapikey and test it.

Drupal 8 config form

5. Debug the configuration object.

We can also debug the configuration object with Drupal Console command debug:config (dc) which give us a list configuration objects names and single configuration object:

Drupal console debug config

 

6. Retrieve the value in a controller class.

To get or set the value of a configuration object in a class, we will need a service. In fact we need the core service 'config.factory'.

We can find it with the Drupal Console commands: drupal debug:container or drupal debug:container config.factory

This service has a method that allows to get the value by its key of a configuration object.

So, when we create the controller, well inject this service to use later.

Lets create the controller and inject the service at the same time with Drupal Console.

drupal generate:controller  --module="ex08" \
--class="ExternalApiKeyController" \
--routes='"title":"External API Key", "name":"ex08.external_api_key_controller_ShowKey", "method":"ShowKey", "path":"/ex08/ShowKey"' \
--services='config.factory' \
--uri="http://default" \
--no-interaction

This command creates the file ExternalApiKeyController.php under /src/Controller and update the ex08.routing.yml file with a new route.

The updated ex08.routing.yml file:

ex08.external_api_key_form:
  path: '/admin/config/ex08/externalapikey'
  defaults:
    _form: '\Drupal\ex08\Form\ExternalApiKeyForm'
    _title: 'ExternalApiKeyForm'
  requirements:
    _permission: 'access administration pages'
  options:
    _admin_route: TRUE

ex08.external_api_key_controller_ShowKey:
  path: '/ex08/ShowKey'
  defaults:
    _controller: '\Drupal\ex08\Controller\ExternalApiKeyController::ShowKey'
    _title: 'External API Key'
  requirements:
    _permission: 'access content'

The new ExternalApiKeyController.php:

configFactory = $config_factory;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('config.factory')
    );
  }

  /**
   * Showkey.
   *
   * @return array
   *
   */
  public function ShowKey() {

    return [
      '#type' => 'markup',
      '#markup' => $this->t('The ShowKey() action')
    ];
  }

}

We can see that the config.factory service has been retrieved from the service container  in the create() method and sent back (dependency injection) to the class itself through the __construct() method. Thank you, Drupal Console!!!

Now, in the ShowKey() method, we need to access the value of our ex08.externalapikey configuration object and get the value of the key your_external_api_key. This is what we can see in the following code:

  public function ShowKey() {

    // Get the configuration object
    $config = $this->configFactory->get('ex08.externalapikey');
    // Get the value of the key 'your_external_api_key' 
    $key = $config->get('your_external_api_key');

    return [
      '#type' => 'markup',
      '#markup' => $this->t('The External API Key is: @key',['@key'=>$key])
    ];
  }

Done!!!

Recap.

1. We created a configuration form, and a route to this form, with the DC command drupal generate:form:config. This form generated a configuration object ('ex08.externalapikey') and a set of key/value pair. In our case, we have just one key/value pair and the key is: 'your_external_api_key'

2. We debugged the key/value pair of the configuration object with the DC command drupal debug:config 

3. We created a controller and injected the service we need (config.factory) to access the config system.
In the controller, we called the service object to get the value of a particular key of the configuration object.

As we can see, today Drupal Console is a must in Drupal 8.

7. Bonus: Retrieve the config value in a hook

Sometimes we need set or get configuration values in a hook, in this case we can't inject the service config.factory by dependency injection.

We’ll use the \Drupal static service container wrapper to do so.

function ex08_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id){
	// Get the config object
	$config = \Drupal::config('ex08.externalapikey');
	// Get the key value
	$key = $config->get('your_external_api_key');
}
Original Post: 

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web