I needed to override the ViewBuilder handler for media entities in a Drupal 11.x project — not subclass it via a custom entity type, but surgically replace the class used by an existing one. hook_entity_type_alter() is exactly the right tool. It receives every registered EntityTypeInterface object by reference after all modules have defined them, so you can call setHandlerClass() on any entity type before the container is compiled.
This is different from hook_entity_type_build(), which runs earlier and is meant for modules defining new types. hook_entity_type_alter() is the post-processing hook — think of it as the last-write-wins override point.
<?php
/**
* Implements hook_entity_type_alter().
*/
function mymodule_entity_type_alter(array &$entity_types): void {
if (isset($entity_types['media'])) {
$entity_types['media']->setHandlerClass(
'view_builder',
\Drupal\mymodule\MediaViewBuilder::class
);
}
}
Make sure your replacement class extends the original handler (or at minimum implements the correct interface), and remember that the handler registry is cached — run drush cr after any change to this hook or Drupal will keep using the old class from the container build.