---
title: "Symfony expression language"
manual: "TYPO3 Explained"
version: "11.5"
permalink: "https://docs.typo3.org/permalink/t3coreapi:symfony-expression-language@11.5"
source: "ApiOverview/SymfonyExpressionLanguage/Index.rst"
rendered: "2026-10-21T15:30:00+00:00"
---

> [!WARNING]
> **Attention**
>
> TYPO3 v11 has reached end-of-life as of October 31th 2024 and
> is no longer being maintained. Use the version switcher on the top
> left of this page to select documentation for a supported version of TYPO3.
>
> Need more time before upgrading?
> You can purchase Extended Long Term Support (ELTS) for TYPO3 v11 here:
> [TYPO3 ELTS](https://typo3.com/services/extended-support-elts).

# Symfony expression language {#symfony-expression-language}

Symfony expression language is used by TYPO3 in certain places. These are
documented in the following sections, together with explanations how they can be
extended:

**This page**

-   [Symfony within TypoScript conditions](https://docs.typo3.org/permalink/t3coreapi:symfony-within-typoscript-conditions@11.5)
-   [Registering new provider within an extension](https://docs.typo3.org/permalink/t3coreapi:registering-new-provider-within-an-extension@11.5)
-   [Implement provider within extension](https://docs.typo3.org/permalink/t3coreapi:implement-provider-within-extension@11.5)
-   [Additional variables](https://docs.typo3.org/permalink/t3coreapi:additional-variables@11.5)
-   [Additional functions](https://docs.typo3.org/permalink/t3coreapi:additional-functions@11.5)

## Symfony within TypoScript conditions {#sel-within-typoscript-conditions}

In order to provide custom conditions, its essential to understand how
conditions are written. Refer to [The syntax of conditions](https://docs.typo3.org/permalink/t3coreapi:typoscript-syntax-conditions-syntax@11.5) for details.

Conditions are evaluated by the [Symfony Expression Language](https://symfony.com/doc/current/components/expression_language.html) and are evaluated
to boolean results. Therefore an integrator can write `[true === true]`
which would evaluate to true. In order to provide further functionality within
conditions, the Symfony Expression Language needs to be extended. There are two
parts that can be added to the language, which are variables and functions.

The following sections explain how to add variables and functions.

## Registering new provider within an extension {#sel-ts-registering-new-provider-within-extension}

There has to be a provider, no matter whether variables or functions will be provided.

The provider is registered in the extension file
`Configuration/ExpressionLanguage.php`:

**EXT:some_extension/Configuration/ExpressionLanguage.php**

```php
return [
    'typoscript' => [
        \MyVendor\SomeExtension\ExpressionLanguage\CustomTypoScriptConditionProvider::class,
    ]
];
```

This will register the defined `CustomTypoScriptConditionProvider` PHP class as provider within the context `typoscript`.

## Implement provider within extension {#sel-ts-implement-provider-within-extension}

The provider itself is written as PHP Class within the extension file
`/Classes/ExpressionLanguage/CustomTypoScriptConditionProvider.php`, depending on
the formerly registered PHP class name:

**EXT:some_extension/Classes/ExpressionLanguage/CustomTypoScriptConditionProvider.php**

```php
namespace MyVendor\SomeExtension\ExpressionLanguage;

use TYPO3\CMS\Core\ExpressionLanguage\AbstractProvider;

class CustomTypoScriptConditionProvider extends AbstractProvider
{
    public function __construct()
    {
    }
}
```

## Additional variables {#sel-ts-additional-variables}

Additional variables can already be provided within the
`CustomTypoScriptConditionProvider` PHP class:

**EXT:some_extension/Classes/ExpressionLanguage/CustomTypoScriptConditionProvider.php**

```php
class CustomTypoScriptConditionProvider extends AbstractProvider
{
    public function __construct()
    {
        $this->expressionLanguageVariables = [
            'variableA' => 'valueB',
        ];
    }
}
```

In above example a new variable `variableA` with value `valueB` is added, this
can be used within conditions:

**EXT:some_extension/Configuration/TypoScript/setup.typoscript**

```typoscript
[variableA === 'valueB']
    page >
    page = PAGE
    page.10 = TEXT
    page.10.value = Matched
[GLOBAL]
```

## Additional functions {#sel-ts-additional-functions}

Additional functions can be provided through another class, which has to be
returned by the example `CustomTypoScriptConditionProvider` PHP class:

**EXT:some_extension/Classes/ExpressionLanguage/CustomTypoScriptConditionProvider.php**

```php
class CustomTypoScriptConditionProvider extends AbstractProvider
{
    public function __construct()
    {
        $this->expressionLanguageProviders = [
            CustomConditionFunctionsProvider::class,
        ];
    }
}
```

The returned class will look like the following:

**EXT:some_extension/Classes/ExpressionLanguage/CustomConditionFunctionsProvider.php**

```php
namespace Vendor\SomeExtension\TypoScript;

use Symfony\Component\ExpressionLanguage\ExpressionFunction;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;

class CustomConditionFunctionsProvider implements ExpressionFunctionProviderInterface
{
    public function getFunctions()
    {
        return [
            $this->getWebserviceFunction(),
        ];
    }

    protected function getWebserviceFunction(): ExpressionFunction
    {
        // TODO: Implement
    }
}
```

The class is already trying to return a new `ExpressionFunction`, but
currently lacks implementation. That is the last step:

**EXT:some_extension/Classes/ExpressionLanguage/CustomConditionFunctionsProvider.php**

```php
protected function getWebserviceFunction(): ExpressionFunction
{
    return new ExpressionFunction('webservice', function () {
        // Not implemented, we only use the evaluator
    }, function ($existingVariables, $endpoint, $uid) {
        return GeneralUtility::getUrl(
            'https://example.org/endpoint/'
            . $endpoint
            .  '/'
            . $uid
        );
    });
}
```

The first argument `$existingVariables` is an array of which each associative key corresponds to a registered variable.

-   request - `\TYPO3\CMS\Core\ExpressionLanguage\RequestWrapper`
-   applicationContext - string
-   typo3 - stdClass
-   tree - stdClass
-   frontend - stdClass
-   backend - stdClass
-   workspace - stdClass
-   page - array: page record

If you need an undefined number of variables, then you can write the same
function in a variadic form:

**EXT:some_extension/Classes/ExpressionLanguage/CustomConditionFunctionsProvider.php**

```php
// ...
}, function (...$args) {
    $existingVariables = $args['0'];
    // ...
}
```

All further arguments are provided by TypoScript. The above example could look like:

**EXT:some_extension/Configuration/TypoScript/setup.typoscript**

```typoscript
[webservice('pages', 10)]
    page.10 >
    page.10 = TEXT
    page.10.value = Matched
[GLOBAL]
```

If a simple string like a page title is returned, this can be further compared:

**EXT:some_extension/Configuration/TypoScript/setup.typoscript**

```typoscript
[webservice('pages', 10) === 'Expected page title']
    page.10 >
    page.10 = TEXT
    page.10.value = Matched
[GLOBAL]
```

Further information about `ExpressionFunction` can be found within [Symfony Expression Language - Registering Functions](https://symfony.com/doc/current/components/expression_language/extending.html#registering-functions)
