Schema Form
The "Schema Form" module automatically generates Drupal forms directly from defined schemas, using the structure, labels, and validation constraints from the schema definition.
It auto-generates forms for configuration entities, config objects like module settings pages, and for any other schema you want!
Simply put, to create a form page, you only need to describe the data schema in a YAML schema file, and that's it. The form page will be generated automatically without any custom code. However, if needed, you can still alter the form and add your customizations on top of the auto-generated form.
Usage
Configuration forms
Let's imagine you developed a custom API client that needs to store the API
configuration and some options. You would describe the schema in the file
config/schema/my_module.schema.yml like this:
my_module.api_endpoint:
type: config_object
label: API Configuration
mapping:
endpoint:
type: uri
label: Endpoint
constraints:
NotBlank: []
username:
type: string
label: Username
constraints:
Regex:
pattern: /^[a-zA-Z0-9_]+$/
message: Only alphanumeric characters and underscores are allowed.
password:
type: string
label: Password
debug_logging:
type: boolean
label: Enable debug logging
Normally, you would then have to create a form, manually listing the same fields and labels, then validate them and save to configs.
But with this module, you do not need to spend time on this! Just describe a route with the config name like this:
my_module.my_api_config:
path: /admin/my-api-config
defaults:
_form: Drupal\schema_form\SchemaConfigFromRouteForm
_title: My API config
options:
_admin_route: TRUE
editable_config_names:
- my_module.my_api_config
requirements:
_permission: administer system
The key part is the editable_config_names option, where you can list one or
more config names that should be exposed as a form. The rest will be done
automatically by the module. You just need to open the configured URL
/admin/my-api-config and you will see a fully working form with all the
fields, validation, and configuration update functionality working out of the
box, without a single line of custom PHP code!
If you need to customize the page, create a simple class extending the
Drupal\schema_form\SchemaConfigFormBase base class like this:
namespace Drupal\my_module\Form;
use Drupal\schema_form\SchemaConfigFormBase;
class MyConfigForm extends SchemaConfigFormBase {
public function getEditableConfigNames() {
return ['schema_form_test.my_config'];
}
}
Then you can declare your own buildForm(), validateForm(), or
submitForm() function to add your custom logic, and call the parent function
to do the rest.
You can find more working examples in the tests/modules/schema_form_test
submodule.
Config entity forms
If you created a custom config entity, there is no need to create and manage the
form class for it—the module will do this automatically. All you need to do is
choose the SchemaFormEntityForm class as a handler for the entity add and
edit forms like this:
use Drupal\schema_form\Form\SchemaFormEntityForm;
#[ConfigEntityType(
id: 'my_custom_config_entity',
...
handlers: [
'form' => [
'add' => SchemaFormEntityForm::class,
'edit' => SchemaFormEntityForm::class,
'delete' => EntityDeleteForm::class,
],
],
...
)]
You can customize the form directly from the Drupal admin panel by creating a
design on the page /admin/config/content/schema-form-design.
See a full example in the file src/Entity/SchemaFormDesign.php.
Regular forms
You can use this module not only for configuration forms, but for any form you want! Instead of building a long PHP array for the form, you just need to describe the schema and that's it. Here is an example:
my_module.my_feedback_form:
type: mapping
label: Send us your feedback
mapping:
first_name:
type: string
label: First name
last_name:
type: string
label: Last name
email:
type: email
label: Your email
constraints:
NotBlank: []
message:
type: text
label: Message text
constraints:
NotBlank: []
description: Please provide your feedback in this field.
Then, just create a simple class extending SchemaFormBase:
namespace Drupal\my_module\Form;
use Drupal\Core\Form\FormStateInterface;
use Drupal\schema_form\SchemaFormBase;
class MyFeedbackForm extends SchemaFormBase {
public function getSchemaFormSchema(): string|null {
return 'schema_form_test.my_feedback_form';
}
public function processSubmittedValues(TraversableTypedDataInterface $values, FormStateInterface $form_state): void {
// Custom handling of already validated form submission typed values.
$valuesArray = $values->getValue();
$name = $valuesArray['first_name'] ?? NULL;
$this->messenger()->addMessage($this->t('Thank you, @name!', [
'@name' => $name ?? $this->t('Anonymous'),
]));
}
}
And that's it! You have a fully working feedback form, without manually filling any PHP array! You can simply process the already validated and typed submission data, without handling this manually.
Look for more demo examples in the submodule tests/modules/schema_form_test.
To install the schema_form_test module on your local website, add this line
to your settings.php:
$settings['extension_discovery_scan_tests'] = TRUE;
Customizing the form
Classic PHP way
You can customize the form as usual by adding additional properties to the form elements in PHP. For example:
class MyFeedbackForm extends SchemaFormBase {
...
public function buildForm(array $form, FormStateInterface $form_state) {
$form = parent::buildForm($form, $form_state);
$form['first_name']['#description'] = $this->t(
"We'll be glad to know your name."
);
return $form;
}
...
}
Schema Form Designs
Schema Form Design entities are used to add customizations to the data defined in the schema while rendering the form.
Using them, you can modify the existing form elements by adding or replacing generated data, without touching the schema.
More details about Schema Form Design are on the separate page Schema Form Designs.
Custom fields directly in the schema file
If you want to keep the form design data directly with the schema, you can put
it into the third_party_settings.schema_form field of the schema. Here is an
example:
You can find more details about this approach in the separate document Additional fields in the schema definition.