[meta] Replace lazy service proxy generation with service closures

Created on 20 March 2025, 22 days ago

Problem/Motivation

As discussed in šŸ“Œ DX: Creating lazy services is too difficult/obscure/bespoke/brittle Active the DX for our current lazy service proxies is poor. We tried using symfony lazy services in šŸ“Œ Deprecate Drupal ProxyBuilder in favor of Symfony lazy services Closed: won't fix however that was not possible due to:

Sadly SF uses eval for the proxy classes which at least I can't see working with our serialized container solution

However we can now use service closures to lazy-load services which are supported by our serialized container.

Steps to reproduce

Proposed resolution

Replacy services tagged 'lazy' with service closures.

Prefer using autowiring and the #[AutowireServiceClosure] attribute over the !service_closure yaml command where possible.

https://symfony.com/doc/current/service_container/autowiring.html#genera...

This requires changing the constructor signature and adding a new method to invoke the closure like so:

Before:

public function __construct(
  protected CronInterface $cron,
) {}

Service definition:

services:
  my_service:
    class: Foo\Bar
    arguments: ['@cron']

After:

public function __construct(
  protected \Closure $cronClosure,
) {}


protected function getCron(): CronInterface {
  return ($this->cronClosure)();
}

Service definition:

services:
  my_service:
    class: Foo\Bar
    arguments: [!service_closure '@cron']

Autowiring approach

Before:

public function __construct(
  protected CronInterface $cron,
) {}

Service definition:

services:
  my_service:
    class: Foo\Bar
    autowire: true

After:

public function __construct(
#[AutowireServiceClosure('cron')]
  protected \Closure $cronClosure,
) {}


protected function getCron(): CronInterface {
  return ($this->cronClosure)();
}

Service definition:

services:
  my_service:
    class: Foo\Bar
    autowire: true

Remaining tasks

Current proxies under core/lib/Drupal/Core/ProxyClass:

ā”œā”€ā”€ Batch
ā”‚   ā””ā”€ā”€ BatchStorage.php
ā”œā”€ā”€ Config
ā”‚   ā””ā”€ā”€ ConfigInstaller.php
ā”œā”€ā”€ Cron.php
ā”œā”€ā”€ Extension
ā”‚   ā””ā”€ā”€ ModuleInstaller.php
ā”œā”€ā”€ File
ā”‚   ā””ā”€ā”€ MimeType
ā”‚       ā”œā”€ā”€ ExtensionMimeTypeGuesser.php
ā”‚       ā””ā”€ā”€ MimeTypeGuesser.php
ā”œā”€ā”€ Lock
ā”‚   ā”œā”€ā”€ DatabaseLockBackend.php
ā”‚   ā””ā”€ā”€ PersistentDatabaseLockBackend.php
ā”œā”€ā”€ Menu
ā”‚   ā””ā”€ā”€ MenuActiveTrail.php
ā”œā”€ā”€ PageCache
ā”‚   ā””ā”€ā”€ ChainResponsePolicy.php
ā”œā”€ā”€ ParamConverter
ā”‚   ā”œā”€ā”€ AdminPathConfigEntityConverter.php
ā”‚   ā””ā”€ā”€ MenuLinkPluginConverter.php
ā”œā”€ā”€ Render
ā”‚   ā””ā”€ā”€ BareHtmlPageRenderer.php
ā””ā”€ā”€ Routing
    ā”œā”€ā”€ MatcherDumper.php
    ā””ā”€ā”€ RouteBuilder.php

Proxies in core modules:

core/modules/language/src/ProxyClass/LanguageConverter.php
core/modules/node/src/ProxyClass/ParamConverter/NodePreviewConverter.php
core/modules/views_ui/src/ProxyClass/ParamConverter/ViewUIConverter.php

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

šŸ“Œ Task
Status

Active

Version

11.0 šŸ”„

Component

base system

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Production build 0.71.5 2024