Repository navigation
Conversation
This was referenced Nov 2, 2026
Closed
phcorp
force-pushed
the
override_template_at_runtime
branch
2 times, most recently
from
November 7, 2026 02:06
4dd7aea to
01d2332
Compare
Templates are configured with Crud::overrideTemplate() in configureCrud() of the dashboard or of the CRUD controller, and AdminContextFactory copies them into the TemplateRegistry of the I18nContext when it builds the admin context. After that, there's no way to change a template, so code that decides the template from the current request (e.g. an event listener that renders a page without the main menu when it's loaded inside a modal dialog, for any CRUD controller) has to change the private registry with reflection. AdminContext::overrideTemplate() (and I18nContext::overrideTemplate()) change a template for the rest of the current request. The template name is validated by TemplateRegistry::setTemplate(), as with Crud. The method is declared with @method in AdminContextInterface, as done for getDashboardComponentDefaults(), to not break its implementations. The alternatives were discarded because they are larger and less useful: exposing the TemplateRegistry leaks an internal class; dispatching an event in CrudResponseListener only covers the responses of CRUD actions, while templates are also resolved by ea.templatePath() in dashboards and custom pages; and a read-only map of runtime overrides would duplicate what the registry already does for the request.
phcorp
force-pushed
the
override_template_at_runtime
branch
from
November 8, 2026 19:51
01d2332 to
9840cfe
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #7897
Problem
Templates are configured with
Crud::overrideTemplate()inconfigureCrud()of the dashboard or of a CRUD controller.AdminContextFactorycopies them into theTemplateRegistryof theI18nContextwhen it builds the admin context, and after that there's no supported way to change a template.Some code needs to pick a template from the current request and for any CRUD controller, so it can't do it in
configureCrud(). One example is an event listener that renders pages without the main menu when they're loaded inside a modal dialog. Such code has to readAdminContext::$i18nContextandI18nContext::$templateRegistrywith reflection to callsetTemplate().Fix
Add
AdminContext::overrideTemplate(string $templateName, string $templatePath), which delegates to a newI18nContext::overrideTemplate(). It changes a template for the rest of the current request. The template name is validated byTemplateRegistry::setTemplate(), the same way as withCrud::overrideTemplate().The method is declared with
@methodinAdminContextInterface, the same way asgetDashboardComponentDefaults(), so existing implementations of the interface don't break.doc/design.rstdocuments it after theoverrideTemplate()/overrideTemplates()examples.Alternatives considered:
TemplateRegistry: this leaks an internal class through the public API.CrudResponseListenerthat lets listeners override templates: it only covers the responses of CRUD actions. Templates are also resolved withea.templatePath()in dashboards and custom pages, and it would add an event class plus a dispatch for a single use.I18nContext::getTemplatePath(): this duplicates what the per-request registry already does.Tests
I18nContextTest,AdminContextTest): the override changes the resolved path, leaves the other templates unchanged, and rejects an unknown template name.OverrideTemplateAtRuntimeTest, CustomizationApp): a test event subscriber onBeforeCrudActionEventoverrideslayoutwhen the request has anX-Override-Layoutheader.body[data-override-layout]) with its rows.Results:
make tests ARGS="tests/Unit/Context tests/Functional/Customization/Crud/Templates": OK (20 tests)make tests-parallel: OK (3691 tests)