Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
By Xano on
Change record status:
Published (View all published change records)
Project:
Introduced in branch:
8.x
Issue links:
Description:
hook_forms()
has been removed, since the functionality can be achieved by class inheritance.
All forms that rely on hook_forms()
need to be converted to a class that implements \Drupal\Core\Form\FormInterface
, and which gets the desired form variation name injected:
Drupal 7
/**
* Implements hook_forms().
*/
function foo_forms() {
return array(
'foo_bar_form' => 'foo_form',
'foo_baz_form' => 'foo_form',
'foo_qux_form' => 'foo_form',
);
}
/**
* Form constructor for foo_form().
*/
function foo_form(array $form, array &$form_state) {
$form['bar'] = array(
'#title' => t('Bar'),
'#type' => 'textfield',
);
return $form;
}
/**
* Menu page callback: Presents the Foo form.
*/
function foo_page() {
return drupal_get_form('foo_bar_form');
}
Drupal 8
class FooForm implements FormInterface {
protected $type;
public function __construct($type) {
$this->type = $type;
}
public function getFormId() {
return 'foo_' . $this->type . '_form';
}
}
class FooRouteController {
public function fooBarForm($type) {
$form = new FooForm('bar');
return \Drupal::formBuilder()->getForm($form);
}
}
Impacts:
Module developers
Comments
Forms with Injected Services
For forms using Dependency Injection, the example shown in the change record won't work that easily. A possible approach in that case is this:
Example form, with ->getformId() resolving to a unique value (via the $location property):
Each unique instance of the form can be created with a helper function like this:
Notice that this helper method can be converted to a lazy builder, so that the form can be rendered in a way that doesn't prevent caching by Dynamic Page Cache (for logged-in users, the form token varies per-user, so it causes an 'UNCACHEABLE' situation).