The settings form
A settings form is a page in the panel where the administrator changes the module configuration. There is a ready base class for it, ConfigFormBase: it adds the "Save configuration" button and the success message. All that is left is to describe the fields and write the values.
Where the form lives
Like an ordinary form — in the src/Form folder of the module. Create the file by hand.
The form class
// web/modules/custom/blog/src/Form/SettingsForm.php
namespace Drupal\blog\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
class SettingsForm extends ConfigFormBase
{
public function getFormId(): string
{
return 'blog_settings_form';
}
protected function getEditableConfigNames(): array
{
return ['blog.settings'];
}
public function buildForm(array $form, FormStateInterface $form_state): array
{
$form['list_title'] = [
'#type' => 'textfield',
'#title' => $this->t('List title'),
'#default_value' => $this->config('blog.settings')->get('list_title'),
];
return parent::buildForm($form, $form_state);
}
public function submitForm(array &$form, FormStateInterface $form_state): void
{
$this->config('blog.settings')
->set('list_title', $form_state->getValue('list_title'))
->save();
parent::submitForm($form, $form_state);
}
}There are three differences from an ordinary form. The getEditableConfigNames() method names the configuration objects the form changes — thanks to it $this->config() returns a writable object here. #default_value puts the current value into the field. And the calls to parent::buildForm() and parent::submitForm() add the button and the message.
The route
Panel pages start with /admin. Settings pages are placed inside /admin/config:
# web/modules/custom/blog/blog.routing.yml
blog.settings:
path: '/admin/config/content/blog'
defaults:
_form: '\Drupal\blog\Form\SettingsForm'
_title: 'Blog settings'
requirements:
_permission: 'administer site configuration'The administrator has the administer site configuration permission. After drush cr open /admin/config/content/blog, change the title and save — the /blog page from the previous lesson shows the new text.
A link in the panel
To make the page easy to find, add a link to blog.links.menu.yml:
# web/modules/custom/blog/blog.links.menu.yml
blog.settings:
title: 'Blog settings'
description: 'The list title and the number of articles per page.'
route_name: blog.settings
parent: system.admin_config_contentThe link appears on the Configuration page in the Content authoring group.
The button in the list of modules
# web/modules/custom/blog/blog.info.yml
configure: blog.settingsThe line is added to the module description file. After drush cr the Extend page shows a Configure link next to the Blog module.
Several fields
Other settings are added the same way — a field in buildForm() and a line in submitForm():
// web/modules/custom/blog/src/Form/SettingsForm.php
$form['items_per_page'] = [
'#type' => 'number',
'#title' => $this->t('Articles per page'),
'#default_value' => $this->config('blog.settings')->get('items_per_page'),
'#min' => 1,
'#max' => 50,
];// web/modules/custom/blog/src/Form/SettingsForm.php
$this->config('blog.settings')
->set('list_title', $form_state->getValue('list_title'))
->set('items_per_page', (int) $form_state->getValue('items_per_page'))
->save();A value from the form arrives as a string, while the schema declares the field as integer, so it is cast to a number.
Common mistake
Every value the form saves must be described in the schema config/schema/blog.schema.yml from the previous lesson. Without it Drupal reports a missing schema, and the value may be saved with the wrong type. When you add a field to the form, add it to the schema and to config/install/blog.settings.yml, then run drush cr.