---
title: "DataSourceAwareProcessor"
manual: "Handlebars"
version: "main"
permalink: "https://docs.typo3.org/permalink/cpsit/typo3-handlebars:developer-corner-data-source-aware-processor@main"
source: "DeveloperCorner/DataSourceAwareProcessor.rst"
rendered: "2026-09-29T09:05:57+00:00"
---

# DataSourceAwareProcessor {#developer-corner-data-source-aware-processor}

Implement the
[\\CPSIT\\Typo3Handlebars\\DataProcessing\\DataSource\\DataSourceAwareProcessor](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:cpsit-typo3handlebars-dataprocessing-datasource-datasourceawareprocessor@main)
interface to run custom PHP logic during the `preProcessing` or
`postProcessing` stages of a `process-variables`
processor (or of `HANDLEBARSTEMPLATE` directly). Unlike standard
TYPO3 data processors, implementations receive a `DataSourceCollection`
that gives structured access to all four data sources available at that point
in the pipeline.

-   **interface DataSourceAwareProcessor**

    -   *Fully qualified name:* `\CPSIT\Typo3Handlebars\DataProcessing\DataSource\DataSourceAwareProcessor`

    -   **process(array $variables, DataSourceCollection $collection, ContentObjectRenderer $contentObjectRenderer)**

        Process the current variable set and return the (modified) array.

        -   *param array $variables:* Current template variable set.
        -   *param DataSourceCollection $collection:* All four data sources for the current rendering.
        -   *param ContentObjectRenderer $contentObjectRenderer:* Current content element renderer.
        -   *returntype:* array

## Reading from DataSourceCollection {#developer-corner-data-source-aware-processor-collection}

`DataSourceCollection::resolve()` searches the data sources in priority
order and returns the first match. Pass a specific `DataSource` case to
restrict the lookup:

```php
use CPSIT\Typo3Handlebars\DataProcessing\DataSource\DataSource;

// Search all sources (highest priority first)
$table = $collection->resolve('table');

// Search only the processor configuration
$table = $collection->resolve('table', DataSource::ProcessorConfiguration);

// Search two specific sources, in the given order
$table = $collection->resolve('table', [
    DataSource::ProcessorConfiguration,
    DataSource::ContentObjectConfiguration,
]);
```

The four `DataSource` cases mirror the `processorConfiguration`,
`processedData`, `contentObjectRenderer` and
`contentObjectConfiguration` identifiers described in
[Data source resolution](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:developer-corner-data-sources@main).

The `$key` argument may use `/` to reach into a nested array
within the searched source(s), e.g. `$collection->resolve('some/nested/key')`
— see [Nested keys](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:developer-corner-data-sources-nested-keys@main).

By default, a key (or path segment) that cannot be found in any searched
source simply yields the given `$default` value (`null` if none is
given). Pass `optional: false` to make `resolve()` throw
`\Exception\PathIsMissingInDataSource` instead, once none of the
searched sources match and no default is configured:

```php
use CPSIT\Typo3Handlebars\Exception;

try {
    $value = $collection->resolve('some/nested/key', optional: false);
} catch (Exception\PathIsMissingInDataSource $exception) {
    // None of the searched sources had "some/nested/key"
}
```

## Resolving a data payload via a configurable keyword {#developer-corner-data-source-aware-processor-keyword}

Processors often accept a configuration option that itself points at the
payload to work with — for example, an `iterable` option
naming the data source to iterate over (see
[Payload resolution](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:developer-corner-data-sources-payload@main) for the full resolution rules).
`DataSourceProvider::provide()` covers this pattern in one call: it
reads the option named by its `$keyword` argument (default
`dataSource`) from `DataSource::ProcessorConfiguration` and
resolves it. Since `DataSourceAwareProcessor` implementations are
instantiated via `GeneralUtility::makeInstance()`, `DataSourceProvider`
can be injected through the constructor like any other service:

```php
use CPSIT\Typo3Handlebars\DataProcessing\DataSource\DataSourceProvider;
use CPSIT\Typo3Handlebars\Exception;

final readonly class MyPreProcessor implements DataSourceAwareProcessor
{
    public function __construct(
        private DataSourceProvider $dataSourceProvider,
    ) {}

    public function process(
        array $variables,
        DataSourceCollection $collection,
        ContentObjectRenderer $contentObjectRenderer,
    ): array {
        try {
            // Resolves the "iterable" processor option, e.g. "processedData:news"
            $variables['items'] = $this->dataSourceProvider->provide($collection, 'iterable');
        } catch (
            Exception\DataSourceIsNotSupported
            | Exception\DataSourceIsMissingInCollection
            | Exception\PathIsMissingInDataSource
        ) {
            // The "iterable" option is not configured, or invalid
        }

        return $variables;
    }
}
```

## Example implementation {#developer-corner-data-source-aware-processor-implement}

**EXT:my_extension/Classes/DataProcessing/MyPreProcessor.php**

```php
namespace Vendor\Extension\DataProcessing;

use CPSIT\Typo3Handlebars\DataProcessing\DataSource\DataSource;
use CPSIT\Typo3Handlebars\DataProcessing\DataSource\DataSourceAwareProcessor;
use CPSIT\Typo3Handlebars\DataProcessing\DataSource\DataSourceCollection;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;

final readonly class MyPreProcessor implements DataSourceAwareProcessor
{
    public function process(
        array $variables,
        DataSourceCollection $collection,
        ContentObjectRenderer $contentObjectRenderer,
    ): array {
        $table = $collection->resolve('table', DataSource::ProcessorConfiguration, 'tt_content');
        $variables['tableName'] = $table;

        return $variables;
    }
}
```

## Registering the processor {#developer-corner-data-source-aware-processor-register}

Reference the processor class by its fully qualified class name in
`preProcessing` or `postProcessing`:

```typoscript
10 = process-variables
10 {
    variables {
        header = TEXT
        header.field = header
    }

    preProcessing {
        10 = Vendor\Extension\DataProcessing\MyPreProcessor
    }
}
```

The numeric keys control execution order when multiple processors are
registered. The class is instantiated via
`GeneralUtility::makeInstance()`, so constructor injection works
as normal.
