Just dumping a few ideas here for discussion:
Method 1: service setter methods.
https://www.previousnext.com.au/blog/safely-extending-drupal-8-plugin-cl...
Example:
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
$instance = parent::create(
$container,
$configuration,
$plugin_id,
$plugin_definition,
$migration
);
$instance->setFooMeddler($container->get('foo.meddler'));
return $instance;
}
/**
* Sets foo meddler.
*/
public function setFooMeddler(FooMeddlerInterface $fooMeddler) {
$this->fooMeddler = $fooMeddler;
}
I feel this is better suited to custom subclasses that you want to be resilient to changes upstream to parent classes.
I don't feel it works for core or contrib code, since when do you get to remove the setter methods?
Method 2: optional parameters with deprecation warnings
Seen in the patch at
https://www.drupal.org/project/drupal/issues/2006632#comment-13147122 →
public function __construct(EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory, TranslationInterface $string_translation, ModuleHandlerInterface $module_handler, AccountInterface $current_user, EntityFieldManagerInterface $entity_field_manager = NULL, EntityDisplayRepositoryInterface $entity_display_repository = NULL, TimeInterface $time = NULL) {
// yada yada
if (!$time) {
@trigger_error('Invoking the CommentManager constructor without the time service parameter is deprecated in drupal:8.8.0 and will no longer be supported in drupal:9.0.0. The time service parameter is now required in the CommentManager constructor. See https://www.drupal.org/node/2785211', E_USER_DEPRECATED);
$time = \Drupal::service('datetime.time');
}
$this->time = $time;
I really like this pattern!