---
title: "YAML API"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:yaml-api@main"
source: "ApiOverview/YamlApi/Index.rst"
rendered: "2026-09-24T12:36:55+00:00"
---

# YAML API {#yaml-api}

YAML is used in TYPO3 for various configurations; most notable are

-   [Event listeners](https://docs.typo3.org/permalink/t3coreapi:eventdispatcher@main) in [`Configuration/Services.yaml`](../../ExtensionArchitecture/FileStructure/Configuration/ServicesYaml.md#file-extension-configuration-services-yaml)
-   [Dependency injection](https://docs.typo3.org/permalink/t3coreapi:dependencyinjection@main) information in
    [`Configuration/Services.yaml`](../../ExtensionArchitecture/FileStructure/Configuration/ServicesYaml.md#file-extension-configuration-services-yaml)
-   [Site configuration](https://docs.typo3.org/permalink/t3coreapi:sitehandling@main) in `sites/<identifier>/config.yaml`
-   System extension [form](https://docs.typo3.org/c/typo3/cms-form/main/en-us/Index.html) configuration
-   System extension [rte_ckeditor](https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/Index.html) configuration

## `YamlFileLoader` {#yamlfileloader}

TYPO3 is using a custom YAML loader for handling YAML in TYPO3 based on the
[symfony/yaml](https://symfony.com/doc/current/components/yaml.html) package. It is located at
`\TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader` and can be used when
YAML parsing is required.

The TYPO3 Core YAML file loader resolves environment variables. Resolving of
variables in the loader can be enabled or disabled via flags. For example, when
editing the site configuration through the backend interface the resolving of
environment variables needs to be disabled to be able to add environment
configuration through the interface.

The format for environment variables is `%env(ENV_NAME)%`. Environment
variables may be used to replace complete values or parts of a value.

The YAML loader class has two flags: `PROCESS_PLACEHOLDERS` and
`PROCESS_IMPORTS`.

-   `PROCESS_PLACEHOLDERS` decides whether or not placeholders (`%abc%`)
    will be resolved.
-   `PROCESS_IMPORTS` decides whether or not imports (`imports` key) will
    be resolved.

Use the method `YamlFileLoader::load()` to make use of the loader in your
extensions:

**EXT:some_extension/Classes/SomeClass.php**

```php
use TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader;

// ...

(new YamlFileLoader())
    ->load(string $fileName, int $flags = self::PROCESS_PLACEHOLDERS | self::PROCESS_IMPORTS)
```

Configuration files can make use of import functionality to reference to the
contents of different files.

Example:

**EXT:my_extension/Configuration/RTE/MyConfiguration.yaml (excerpt)**

```yaml
imports:
  - { resource: "EXT:rte_ckeditor/Configuration/RTE/Processing.yaml" }
  - { resource: "misc/my_options.yaml" }
  - { resource: "../path/to/something/within/the/project-folder/generic.yaml" }
  - { resource: "./**/*.yaml", glob: true }
  - { resource: "EXT:core/Tests/**/Configuration/**/SiteConfigs/*.yaml", glob: true }

# ...

```

The YAML file loader supports importing of files with [glob](https://www.php.net/manual/en/function.glob.php) patterns.
To enable globbing, set the option `glob: true` on the import level.

The files are imported in the order they appear in the importing file. It used to be
the reverse order, take care when updating projects from before v12!

### Custom placeholder processing {#yaml-file-loader-custom-placeholder-processing}

It is possible to register custom placeholder processors to allow fetching data
from different sources. To do so, register a custom processor via
`config/system/additional.php`:

**config/system/additional.php | typo3conf/system/additional.php**

```php
$GLOBALS['TYPO3_CONF_VARS']['SYS']['yamlLoader']['placeholderProcessors']
    [\Vendor\MyExtension\PlaceholderProcessor\CustomPlaceholderProcessor::class] = [];
```

There are some options available to sort or disable placeholder processors, if
necessary:

**config/system/additional.php | typo3conf/system/additional.php**

```php
<?php

$GLOBALS['TYPO3_CONF_VARS']['SYS']['yamlLoader']['placeholderProcessors']
    [\Vendor\MyExtension\PlaceholderProcessor\CustomPlaceholderProcessor::class] = [
      'before' => [
        \TYPO3\CMS\Core\Configuration\Processor\Placeholder\ValueFromReferenceArrayProcessor::class,
      ],
      'after' => [
        \TYPO3\CMS\Core\Configuration\Processor\Placeholder\EnvVariableProcessor::class,
      ],
      'disabled' => false,
    ];

```

New placeholder processors must implement the
`\TYPO3\CMS\Core\Configuration\Processor\Placeholder\PlaceholderProcessorInterface`.
An implementation may look like the following:

**EXT:my_extension/Classes/Configuration/Processor/Placeholder/ExamplePlaceholderProcessor.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Configuration\Processor\Placeholder;

use TYPO3\CMS\Core\Configuration\Processor\Placeholder\PlaceholderProcessorInterface;

final class ExamplePlaceholderProcessor implements PlaceholderProcessorInterface
{
  public function canProcess(string $placeholder, array $referenceArray): bool
  {
    return str_contains($placeholder, '%example(');
  }

  public function process(string $value, array $referenceArray)
  {
    // do some processing
    $result = $this->getValue($value);

    // Throw this exception if the placeholder can't be substituted
    if ($result === null) {
      throw new \UnexpectedValueException('Value not found', 1581596096);
    }
    return $result;
  }

  private function getValue(string $value): ?string
  {
    // implement logic to fetch specific values from an external service
    // or just add simple mapping logic - whatever is appropriate
    $aliases = [
      'foo' => 'F-O-O',
      'bar' => 'ARRRRR',
    ];
    return $aliases[$value] ?? null;
  }
}

```

This may be used, for example, in the site configuration:

**config/sites/\<some_site>/config.yaml**

```yaml
someVariable: '%example(somevalue)%'
anotherVariable: 'inline::%example(anotherValue)%::placeholder'
```

If a new processor returns a string or number, it may also be used inline as
above. If it returns an array, it cannot be used inline since the whole content
will be replaced with the new value.
