Fatal error on attempting to load a PHP class of the theme when switching the theme

Created on 28 November 2024, 5 months ago

Problem/Motivation

This base theme is using PHP classes and is using the service container for resolving those classes. Example:

/**
 * Implements hook_form_alter().
 */
function ui_suite_bootstrap_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
  /** @var \Drupal\ui_suite_bootstrap\HookHandler\FormAlter $instance */
  $instance = \Drupal::service('class_resolver')
    ->getInstanceFromDefinition(FormAlter::class);
  $instance->alter($form, $form_state, $form_id);
}

This works fine as long as the theme is being bootstrapped alongside the kernel. However, when switching to the theme during a request, classes of the theme are not part of the autoload discovery and will therefore fail when attempting to load them:

InvalidArgumentException: Class "Drupal\ui_suite_bootstrap\HookHandler\FormAlter" does not exist. in Drupal\Core\DependencyInjection\ClassResolver->getInstanceFromDefinition() (line 37 of core/lib/Drupal/Core/DependencyInjection/ClassResolver.php).

ui_suite_bootstrap_form_alter() (Line: 458)
Drupal\Core\Theme\ThemeManager->alterForTheme() (Line: 467)
Drupal\Core\Theme\ThemeManager->alter() (Line: 835)
Drupal\Core\Form\FormBuilder->prepareForm() (Line: 285)
Drupal\Core\Form\FormBuilder->buildForm() (Line: 73)
Drupal\Core\Controller\FormController->getContentResult()
call_user_func_array() (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 638)
Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 121)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext() (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 181)
Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 76)
Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 53)
Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 28)
Drupal\Core\StackMiddleware\ContentLength->handle() (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass() (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle() (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 36)
Drupal\Core\StackMiddleware\AjaxPageState->handle() (Line: 51)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle() (Line: 741)
Drupal\Core\DrupalKernel->handle() (Line: 19)

There are some existing and interesting notes around that:
https://drupal.stackexchange.com/questions/279085/is-it-possible-autoloa...

And looking into this code snippet of the "bootstrap" project:
https://git.drupalcode.org/project/bootstrap/-/commit/00f75b9e31f4933258...
It does not like this could have been fixed with much confidence.

Steps to reproduce

TBD - I will try to provide simple steps to reproduce. What I'm currently doing is that I'm switching from the admin theme to the frontend theme on a form_alter hook where this error occurs which originates from the problem described in the links above.

In general, it seems that it's not a good idea to use service-based mechanics in a theme. It seems this is a task solely for modules. Looking at core's existing themes, they almost have no PHP classes at all. Olivero has only one class "OliveroPreRender" which is being used at one place - probably that's why there has no such error been occurred yet.

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

🐛 Bug report
Status

Active

Version

5.1

Component

Code

Created by

🇩🇪Germany mxh Offenburg

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

Comments & Activities

  • Issue created by @mxh
  • 🇩🇪Germany mxh Offenburg
  • 🇫🇷France Grimreaper France 🇫🇷

    Hello,

    Could you provide the example code to reproduce the bug please?

    And try to provide a MR based on what you spotted in the other Bootstrap theme?

  • 🇩🇪Germany mxh Offenburg

    I have tried to write a test for this, but it seems I cannot reproduce it anymore for now. I also currently don't work on the site anymore where I encountered this problem. I've also tried to reproduce this on a fresh Drupal installation with standard profile, writing a hook_form_alter implementation in a module and switch to a theme that is using this theme as base. But still no success.

    The only thing that I can think of is that maybe the composer autoloading settings are different. But unfortunately I have no more time to spend on trying to reproduce this.

    So maybe can be closed as "cannot reproduce" for now?

  • 🇫🇷France Grimreaper France 🇫🇷

    Ok,

    Thanks for your feedback.

    Do no hesitate to reopen if needed.

Production build 0.71.5 2024