Skip to main content
Start of main content.

Our contributions to Drupal 11.4 - and the 11.x journey so far

Michael's post

Drupal 11.4 is here. Several features landing in this cycle, and across the broader 11.x series, trace back to ideas we explored in contrib first. Worth noting too: Drupal major releases don't introduce new features. The real architectural work happens in the minors, and by the time 12.0 arrives, much of it will already be available, paving the way for the next series of improvements in 12.x.

Here's what we've been working on, and what else is worth knowing about.

What we helped build

dr - a proper Drupal CLI (11.4)

The dr CLI entry point lands in Drupal 11.4, and @dpi played a key role in getting it there. His Dex proposal explored what a proper extensible entry point for Drupal CLI commands should look like, and that thinking carried through into the final implementation.

Previously, core/scripts/drupal was limited to running commands defined in core itself. With dr, available at vendor/bin/dr, any module can now register Symfony Console commands via the #[AsCommand] attribute and have them automatically discovered.

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;

#[AsCommand(name: 'mymodule:do-thing')]
class DoThingCommand extends Command {
  // ...
}

It's a small change with a big quality-of-life payoff. Drush has long filled this gap in contrib, but having an extensible CLI built into core is a meaningful step.


Bundle class attributes (11.4)

Drupal 11.4 adds support for registering entity bundle classes via a PHP attribute, as covered in the change record and original issue. @mstrelan had already proven out the idea in the Bundle Classes Attribute (BCA) contrib module, which lets you do exactly this, rather than going through hook_entity_bundle_info_alter().

Now, instead of wiring up a bundle class via a hook, you annotate the class itself:

use Drupal\Core\Entity\Attribute\Bundle;
use Drupal\node\Entity\Node;

#[Bundle(
  entity_type: 'node',
  bundle: 'article',
)]
class ArticleNode extends Node {
  // Bundle-specific methods here.
}

It's consistent with how plugins and hooks are registered elsewhere in Drupal 11, and it removes the boilerplate that was previously required via a hook in a separate file.


OOP hooks - ongoing since 11.1, still evolving

@dpi built Hux in 2022 as a proof of concept: what if Drupal hooks could be implemented in proper PHP classes with dependency injection, instead of procedural .module files? Read the original blog post introducing Hux. It resonated with the community, and became part of the thinking that led to the core OOP hooks initiative that landed in Drupal 11.1.

The core effort has been primarily led by community member @nicxvan, and each release in the 11.x series has pushed the initiative further:

  • 11.1 - core #[Hook] attribute support, autowired services, automatic discovery in src/Hook/
  • 11.2 - hook ordering via new attributes (Order::First, Order::Last, OrderBefore, OrderAfter), replacing the long-standing hook_module_implements_alter(); preprocess hooks now supported
  • 11.3 - theme hooks gain full OOP support, meaning themes can now implement hooks in src/Hook/ classes just like modules; Drupal core itself is progressively converting its own hook implementations
  • 11.4 - continued conversion of core hooks; the ecosystem is maturing

The end state this is heading toward is clear: .module and .theme files will be deprecated. Hooks become services. Drupal-specific patterns that have long been a barrier to onboarding are being replaced with standard PHP and Symfony conventions. It's one of the most significant shifts in developer experience since Drupal 8.

Much of the remaining work, and the path into Drupal 12, involves completing the conversion of core's own hooks, closing edge cases (install hooks are still being worked through), and ensuring contrib has a smooth migration path.


Also worth calling out

drupalGet() in kernel tests (11.4)

Kernel tests are fast, much faster than full functional browser tests, but they've historically been unable to make real HTTP requests. That meant any test involving a route response required a heavier functional test.

The change record introduced drupalGet() to kernel tests, letting them fire actual HTTP requests against a lightweight kernel stack. Most of the underlying work (#3390193) was led by @joachim, allowing us and others to start putting it to use: @mstrelan has been busy converting tests into modules, including help, navigation, and system, and contributing improvements to the trait itself along the way.

If you write Drupal tests, this is worth knowing about. The testing pyramid gets a little more usable.


Default Admin theme - Gin comes to core

Claro has been the default admin theme in Drupal core for a while now, but it's showing its age. Gin, which is used by Drupal CMS, is much closer to what you'd expect from a modern CMS admin interface. The answer is to bring Gin into core as the new default_admin theme, replacing Claro as the default for new installations. Claro will remain available for existing sites, but is planned for removal in Drupal 12.

The new theme brings dark mode, accent colour configuration, layout density controls, and the modern feel that Drupal CMS users are already used to. If you've been running Gin in contrib (and many of us have), this is welcome news.


symfony/runtime

Drupal 11.4 adopts symfony/runtime, which separates the bootstrap process from the entry point. For most sites, this is invisible, but the potential here is significant. symfony/runtime opens the door to running Drupal in new contexts, such as a worker process, serverless, or alongside other Symfony applications, without the bootstrap being tied to a specific entry point. It's an architectural shift that makes Drupal more composable, and one that contrib and hosting tooling can start building on. If you have a custom index.php or non-standard front controller, check the change record before upgrading.


HTMX (landed in 11.3)

Worth a mention even though it landed in 11.3: HTMX is a tiny, dependency-free JavaScript library that lets you build dynamic, server-driven UIs from HTML attributes rather than custom JavaScript. It was added as a dependency in 11.2, became fully featured in 11.3, and the initiative is still going.

The 11.3 milestone was significant: Drupal's BigPipe streaming was updated to use HTMX, cutting the JavaScript footprint for browser-server interactions by up to 71%, and developers got a Htmx factory class for generating HTMX attributes programmatically alongside extended FormBuilder support for HTMX-driven form rebuilds. But like OOP hooks, this is a multi-release effort. The goal is to progressively replace Drupal's aging, home-grown AJAX and form interaction patterns with something lighter and more standard. Expect the initiative to continue through 11.4 and into Drupal 12.


Getting contrib ready for Drupal 12 - the Project Update Bot

With Drupal 12 due later this year, thousands of contributed modules and themes will need updating for breaking changes. Doing that by hand across all of contrib would cost the community an enormous number of hours. The Project Update Bot exists to do that automatically: it scans contributed projects, identifies deprecated API uses, and opens issues with ready-to-apply patches. It now covers over 80% of the deprecated APIs being removed in Drupal 12.

If you maintain a contrib module or theme, it's worth checking your issue queue - there may already be a merge request waiting for you.


Where we sit in the Drupal ecosystem

None of this happens in a vacuum. PreviousNext is Australia's only Top Tier Drupal Certified Partner, and consistently one of the top three global contributors to Drupal core. We invest a significant portion of our time directly into the codebase our clients depend on.

The pattern across our contributions reflects how open source works at its best: we build something in contrib to solve a real problem, the community tests it, refines it, and if it holds up, it finds a home - whether that's core, Drupal CMS, or a well-maintained contrib project. That's how Hux, BCA and Dex all made their way into core

As Drupal 12 takes shape, we'll keep contributing. If you're a developer or agency looking to get more involved, the Drupal issue queue is always open. The best contributions come from people solving real problems, and that's as true today as it's ever been.

Related Articles