Change record status: 
Project: 
Introduced in branch: 
main
Introduced in version: 
11.5.0
Description: 

Plugin, controller, form classes, and other classes implementing either Drupal\Core\Plugin\ContainerFactoryPluginInterface or Drupal\Core\DependencyInjection\ContainerInejctionInterface can now emulate injecting service closures as class properties. This allows the classes to instantiate the services they use lazily.

Service closure properties in these classes are designated to be safely serialized with the Drupal\Core\DependencyInjection\Attribute\ServiceClosure when the classes use Drupal\Core\DependencyInjection\DependencySerializationTrait. DependencySerializationTrait will also repopulate the corresponding class properties with their respective service closure values when the serialized class string is unserialized.

For example:

use Drupal\Core\DependencyInjection\Attribute\ServiceClosure;

class ExampleForm extends FormBase {

  #[ServiceClosure('example.service')]
  protected \Closure $exampleServiceClosure;

  public function __construct(\Closure $exampleServiceClosure) {
    $this->exampleServiceClosure = $exampleServiceClosure;
  }

  public static function create(ContainerInterface $container, ...) {
    return new static(
      static fn(): ExampleServiceInterface => $container->get('example.service'),
    );
  }
  ...
}

Or with property promotion:

use Drupal\Core\DependencyInjection\Attribute\ServiceClosure;

class ExampleForm extends FormBase {

  public function __construct(
    #[ServiceClosure('example.service')]
    protected \Closure $exampleServiceClosure,
  ) {}

  public static function create(ContainerInterface $container): static {
    return new static(
      static fn(): ExampleServiceInterface => $container->get('example.service'),
    );
  }
  ...
}

In the example above, the example.service service object itself can be accessed by calling ($this->exampleServiceClosure)()

To support the use of service closures, passing the LayoutTempstoreRepository service object directly to the Drupal\layout_builder\Form\MoveBlockForm class constructor has been deprecated.

Impacts: 
Module developers