Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

State Processors in Detail

State Processors in Detail

~14 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

State processors are the WRITE counterpart to chapter 57 – INSTEAD of READING data, they process data AFTER validation, BEFORE the final response.

The ProcessorInterface

api/src/State/ExampleProcessor.php
<?php

declare(strict_types=1);

namespace App\State;

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;

final class ExampleProcessor implements ProcessorInterface
{
    public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
    {
        // $data: the (already validated) object from the request body
        // Return: the object the client sees in the response
        return $data;
    }
}

$data is ALREADY the deserialized AND validated object (block 3) – a processor NEVER sees invalid data, validation RUNS BEFOREHAND, INDEPENDENT of the processor.

When to use a processor instead of Doctrine lifecycle callbacks

The Symfony course used Doctrine #[ORM\PrePersist] callbacks for SIMILAR purposes – in API Platform, state processors are the PREFERRED choice, since they ALSO work with non-Doctrine resources (chapter 60) and are MORE EXPLICITLY VISIBLE in the #[ApiResource] configuration.

Handling the DELETE case

public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
{
    if ($operation instanceof \ApiPlatform\Metadata\Delete) {
        // $data is the object being DELETED, BEFORE the delete
    }

    return $this->persistProcessor->process($data, $operation, $uriVariables, $context);
}

Achtung: For Delete operations, process() MUST ALWAYS return null (there's NO object left after deletion) – the wrapped default processor handles this AUTOMATICALLY and CORRECTLY, CUSTOM processor implementations (without wrapping) must handle this THEMSELVES.

Chaining multiple processors

A processor can inject and CALL another processor – EXACTLY how UserPasswordHasherProcessor (chapter 48) wraps the DEFAULT Doctrine processor. Multiple CUSTOM processors can theoretically be NESTED; in PRACTICE, ONE processor per resource usually stays CLEARER.

Tipp: $context contains ADDITIONAL metadata (among other things previous_data on PUT/PATCH, the OLD state BEFORE the change) – useful for detecting in CUSTOM logic WHAT specifically changed.