Adding PHP Function to Symfony ExpressionLanguage, The Simple Way

Today I want to share a quick tip for Symfony users ✌️. When you use the ExpressionLanguage component you get a context: some variables and some functions. Those functions are not the same everywhere.…

Fév 28, 2025 - 17:46
 0
Adding PHP Function to Symfony ExpressionLanguage, The Simple Way

Today I want to share a quick tip for Symfony users ✌️. When you use the ExpressionLanguage component you get a context: some variables and some functions.

Those functions are not the same everywhere. For example when using the validation constraint Expression:

#[Assert\Expression(
  "is_valid(this.getCategory()) or is_valid(this.getSection())",
  message: 'Bad category!',
)]
class BlogPost
{
    // ...
}

You get a custom ExpressionLanguage service, defined like this:

// The language itself with a custom provider
->set('validator.expression_language', ExpressionLanguage::class)
    ->args([service('cache.validator_expression_language')->nullOnInvalid()])
    ->call('registerProvider', [
        service('validator.expression_language_provider')->ignoreOnInvalid(),
    ])

// The custom provider
->set('validator.expression_language_provider', ExpressionLanguageProvider::class)

This service has a provider attached, it's the proper way to extend the functionality in ExpressionLanguage. It implements the interface ExpressionFunctionProviderInterface and looks like this:

class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface
{
    public function getFunctions(): array
    {
        return [
            new ExpressionFunction('is_valid', function (...$arguments) {
                return true; // Redacted for clarity
            }, function (array $variables, ...$arguments): bool {
                return true; // Redacted for clarity
            }),
        ];
    }
}

It's great to add custom functions (is_valid here), but what if I just need to add count() support?!

The recommended way is to use this interface like that, with the fromPhp shortcut:

class CustomExpressionLanguageProvider implements ExpressionFunctionProviderInterface
{
    public function getFunctions(): array
    {
        return [
            ExpressionFunction::fromPhp('count');
        ];
    }
}