Skip to main content
Home
Drupal life hacks

Main navigation

  • Drupal
  • React
  • WP
  • Contact
  • About
User account menu
  • Log in

Breadcrumb

  1. Home

Drupal 11.3 Deprecates template_preprocess_HOOK and file/includes in hook_theme(). What Developers Need to Change

By admin, 17 October, 2025

Drupal 11.3 introduces an important shift for theme and module developers:
the long-standing automatic discovery of template_preprocess_HOOK() functions is now deprecated, along with the file and includes keys in hook_theme().

These patterns have been around since Drupal 7 and worked well in the procedural era. But with modern autoloading and class-based preprocessors, they’re no longer necessary — and now officially discouraged.

In this article, we’ll cover:

  • What exactly is deprecated
  • Why this change was made
  • How to migrate your code to the new standard
  • A complete before/after code example

What’s Being Deprecated?

Old MechanismStatus in 11.3Modern Replacement
template_preprocess_HOOK()DeprecatedExplicit class-based preprocess callbacks
file in hook_theme()DeprecatedRemove — autoloading handles includes
includes in hook_theme()DeprecatedRemove

Why Remove These Features?

Historically, Drupal scanned all loaded PHP files and automatically detected functions named template_preprocess_{hook}. If those functions lived in separate include files, developers had to manually specify them via file or includes in hook_theme().

This “magic” discovery is now considered unpredictable and outdated. Drupal core is moving toward explicit, PSR-4 autoloaded, class-based callbacks, making code easier to trace and refactor.


How to Upgrade Your Code

❌ Before (deprecated approach)

function mymodule_theme() {
  return [
    'my_template' => [
      'variables' => ['items' => NULL],
      'file' => 'mymodule.preprocess.inc',
    ],
  ];
}

function template_preprocess_my_template(&$variables) {
  $variables['items'][] = 'Legacy preprocess';
}

✅ After (modern, future-proof approach)

function mymodule_theme() {
  return [
    'my_template' => [
      'variables' => ['items' => NULL],
      'preprocess' => [
        [\Drupal\mymodule\Theme\MyTemplatePreprocess::class, 'preprocess'],
      ],
    ],
  ];
}
// src/Theme/MyTemplatePreprocess.php

namespace Drupal\mymodule\Theme;

class MyTemplatePreprocess {
  public static function preprocess(array &$variables) {
    $variables['items'][] = 'OOP preprocess FTW';
  }
}

Do You Need to Migrate Right Now?

ScenarioRecommendation
Maintaining a public contrib module✅ Yes — update for Drupal 11.x compatibility
Running an internal Drupal 10 site⚠ Not urgent — but plan ahead before upgrading
Starting new theme or module work🚀 Use the new pattern from day one

Final Thoughts

This move is part of Drupal’s broader transition away from procedural “magic” toward explicit, discoverable, class-based architecture. Preprocess functions still exist — but they must now be registered intentionally via callbacks instead of being auto-detected.

Got legacy code still relying on template_preprocess_* or file/includes? Now’s the perfect time to refactor.

 

Tags

  • #Drupal Planet
  • Drupal preprocess callbacks

Comments

About text formats

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
Powered by Drupal