From: https://www.drupal.org/core/d8-bc-policy#constructors
The constructor for a service object (one in the container), plugin, or controller is considered internal unless otherwise marked, and may change in a minor release. These are objects where developers are not expected to call the constructor directly in the first place. Constructors for value objects where a developer will be calling the constructor directly are excluded from this statement.
The Webform module's service objects, plugins, and controllers have been refactored to rely on the dependency injection container for adding new services instead of overriding the constructor.
For more information and background information, please read…
- A bump in the Webform module's road to Drupal 9
- Safely extending Drupal 8 plugin classes without fear of constructor changes
- Drupal 9 is coming: Getting your code ready
Example
Below is the before and after for this new approach applied to the Drupal\webform\Plugin\WebformHandler\EmailWebformHandler plugin.
Before
Look at the very scary and overwhelming EmailWebformHandler::__construct method with too many parameters.
namespace Drupal\webform\Plugin\WebformHandler;
class EmailWebformHandler extends WebformHandlerBase implements WebformHandlerMessageInterface {
...
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, LoggerChannelFactoryInterface $logger_factory, ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, WebformSubmissionConditionsValidatorInterface $conditions_validator, AccountInterface $current_user, ModuleHandlerInterface $module_handler, LanguageManagerInterface $language_manager, MailManagerInterface $mail_manager, WebformThemeManagerInterface $theme_manager, WebformTokenManagerInterface $token_manager, WebformElementManagerInterface $element_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $logger_factory, $config_factory, $entity_type_manager, $conditions_validator);
$this->currentUser = $current_user;
$this->moduleHandler = $module_handler;
$this->languageManager = $language_manager;
$this->mailManager = $mail_manager;
$this->themeManager = $theme_manager;
$this->tokenManager = $token_manager;
$this->elementManager = $element_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('logger.factory'),
$container->get('config.factory'),
$container->get('entity_type.manager'),
$container->get('webform_submission.conditions_validator'),
$container->get('current_user'),
$container->get('module_handler'),
$container->get('language_manager'),
$container->get('plugin.manager.mail'),
$container->get('webform.theme_manager'),
$container->get('webform.token_manager'),
$container->get('plugin.manager.webform.element')
);
}
...
}
After
The new code is now much simpler, cleaner, and easier to read.
namespace Drupal\webform\Plugin\WebformHandler;
class EmailWebformHandler extends WebformHandlerBase implements WebformHandlerMessageInterface {
...
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
$instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
$instance->currentUser = $container->get('current_user');
$instance->moduleHandler = $container->get('module_handler');
$instance->languageManager = $container->get('language_manager');
$instance->mailManager = $container->get('plugin.manager.mail');
$instance->themeManager = $container->get('webform.theme_manager');
$instance->tokenManager = $container->get('webform.token_manager');
$instance->elementManager = $container->get('plugin.manager.webform.element');
return $instance;
}
...
}
Any contrib module or custom code that extends a Webform service object, plugin, or controller may be broken by this change and will need to be reworked to support this new implementation pattern. This new implementation pattern is backward compatible and will work with both Webform 5,x and 6.x releases.
Comments
See https://www.drupal.org
See https://www.drupal.org/project/drupal/issues/3030640 for why the same doesn't apply to core.