You are browsing a version that has not yet been released. |
Entity Value Resolver Expressions
|
Registering expression language providers for the entity value resolver, and the security functions described below, are new in DoctrineBundle 3.4. |
The #[MapEntity] attribute of Symfony's Doctrine bridge can fetch an entity
through an expression, evaluated with the ExpressionLanguage component. Besides
the request attributes and the repository variable provided by Symfony, the
bundle registers the security functions current_user(), is_granted(),
is_authenticated(), is_fully_authenticated() and is_remember_me().
current_user() returns the currently authenticated user, or null when
there is none:
<?php// VisitController.phpuse App\Entity\Visit;use Symfony\Bridge\Doctrine\Attribute\MapEntity;class VisitController{ public function index( #[MapEntity(class: Visit::class, expr: 'repository.findLatest(current_user())')] iterable $visits, ) { // ... }}
The functions come from the security.expression_language_provider service of
SecurityBundle, so they require Symfony 8.2 or higher, and they are only registered
when the Security component is in use. They read the security context of the current
request: in a console command resolved by
Symfony\Bridge\Doctrine\ArgumentResolver\Console\EntityValueResolver there is no
such context, so evaluating them throws a LogicException rather than reporting
that nobody is authenticated.
Registering your own functions
Tag a service implementing Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface
with doctrine.orm.entity_value_resolver.expression_language_provider to add
your own functions to those expressions:
<?php// ExpressionLanguageProvider.phpuse Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;use Symfony\Component\ExpressionLanguage\ExpressionFunction;use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;#[AutoconfigureTag('doctrine.orm.entity_value_resolver.expression_language_provider')]class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface{ public function getFunctions(): array { return [ new ExpressionFunction( 'current_locale', static fn () => throw new \LogicException('The "current_locale" function cannot be compiled.'), fn (array $variables) => $variables['request']->getLocale(), ), ]; }}
The function is then available in any #[MapEntity] expression:
#[MapEntity(class: Article::class, expr: 'repository.findTranslated(current_locale())')]
With Symfony 8.2 and higher, the expressions of #[MapEntity] are compiled while
the cache is warmed up. A function whose compiler throws is then called through its
evaluator instead, so declaring a throwing compiler is safe: it only keeps the
expression from being fully compiled.
Version compatibility
The doctrine.orm.entity_value_resolver.expression_language_provider tag requires
symfony/expression-language, which #[MapEntity] expressions already need. It
works with every version of the component the bundle supports (6.4 or higher).
The security functions are only registered when symfony/security-bundle 8.2 or
higher is installed, where the security.expression_language_provider service
exists, and when the Security component is in use. With older versions,
#[MapEntity] expressions keep working, but the security functions are not
available in them.
