Skip to content

ObjectMapper fails on DELETE with stateOptions #7612

@valentingoulier

Description

@valentingoulier

API Platform version(s) affected: 4.2.10

Description

I’m encountering an issue when using stateOptions with the ObjectMapper on a DELETE operation.
With the default operations, the DELETE method uses the ApiPlatform\State\Processor\ObjectMapperProcessor class and tries to map a null entity, since the processor has just deleted the entity.

Here is the resulting error:

{
    "@context": "\/contexts\/Error",
    "@id": "\/errors\/500",
    "@type": "Error",
    "title": "An error occurred",
    "detail": "ApiPlatform\\State\\ObjectMapper\\ObjectMapper::map(): Argument #1 ($source) must be of type object, null given, called in \/app\/vendor\/api-platform\/state\/Processor\/ObjectMapperProcessor.php on line 71",
    "status": 500,
    "type": "\/errors\/500",
    "description": "ApiPlatform\\State\\ObjectMapper\\ObjectMapper::map(): Argument #1 ($source) must be of type object, null given, called in \/app\/vendor\/api-platform\/state\/Processor\/ObjectMapperProcessor.php on line 71",
    "trace": [
        {
            "file": "\/app\/vendor\/api-platform\/state\/Processor\/ObjectMapperProcessor.php",
            "line": 71,
            "function": "map",
            "class": "ApiPlatform\\State\\ObjectMapper\\ObjectMapper",
            "type": "-\u003E"
        },
        {
            "file": "\/app\/vendor\/api-platform\/state\/Processor\/WriteProcessor.php",
            "line": 58,
            "function": "process",
            "class": "ApiPlatform\\State\\Processor\\ObjectMapperProcessor",
            "type": "-\u003E"
        },
        {
            "file": "\/app\/vendor\/api-platform\/symfony\/Controller\/MainController.php",
            "line": 125,
            "function": "process",
            "class": "ApiPlatform\\State\\Processor\\WriteProcessor",
            "type": "-\u003E"
        },
        {
            "file": "\/app\/vendor\/symfony\/http-kernel\/HttpKernel.php",
            "line": 183,
            "function": "__invoke",
            "class": "ApiPlatform\\Symfony\\Controller\\MainController",
            "type": "-\u003E"
        },
        {
            "file": "\/app\/vendor\/symfony\/http-kernel\/HttpKernel.php",
            "line": 76,
            "function": "handleRaw",
            "class": "Symfony\\Component\\HttpKernel\\HttpKernel",
            "type": "-\u003E"
        },
        {
            "file": "\/app\/vendor\/symfony\/http-kernel\/Kernel.php",
            "line": 191,
            "function": "handle",
            "class": "Symfony\\Component\\HttpKernel\\HttpKernel",
            "type": "-\u003E"
        },
        {
            "file": "\/app\/vendor\/symfony\/runtime\/Runner\/FrankenPhpWorkerRunner.php",
            "line": 50,
            "function": "handle",
            "class": "Symfony\\Component\\HttpKernel\\Kernel",
            "type": "-\u003E"
        },
        {
            "function": "{closure:Symfony\\Component\\Runtime\\Runner\\FrankenPhpWorkerRunner::run():40}",
            "class": "Symfony\\Component\\Runtime\\Runner\\FrankenPhpWorkerRunner",
            "type": "-\u003E"
        },
        {
            "file": "\/app\/vendor\/symfony\/runtime\/Runner\/FrankenPhpWorkerRunner.php",
            "line": 57,
            "function": "frankenphp_handle_request"
        },
        {
            "file": "\/app\/vendor\/autoload_runtime.php",
            "line": 32,
            "function": "run",
            "class": "Symfony\\Component\\Runtime\\Runner\\FrankenPhpWorkerRunner",
            "type": "-\u003E"
        },
        {
            "file": "\/app\/public\/index.php",
            "line": 5,
            "function": "require_once"
        }
    ]
}

How to reproduce

Here is an API Resource that is causing an issue:

#[ApiResource(
    shortName: 'Usine',
    stateOptions: new Options(entityClass: Usine::class),
)]
#[Map(source: Usine::class, target: Usine::class)]
final class UsineResource
{
    #[ApiProperty(identifier: true)]
    #[Groups(['usine:read'])]
    public ?Ulid $id = null;

    #[Groups(['usine:read', 'usine:write'])]
    public ?string $nom = null;
}

Here is an API Resource that is currently working:

#[ApiResource(
    shortName: 'Usine',
    stateOptions: new Options(entityClass: Usine::class),
    operations: [
        new GetCollection(),
        new Get(),
        new Post(),
        new Patch(),
        new Delete(
            map: false,
        ),
    ],
)]
#[Map(source: Usine::class, target: Usine::class)]
final class UsineResource
{
    #[ApiProperty(identifier: true)]
    #[Groups(['usine:read'])]
    public ?Ulid $id = null;

    #[Groups(['usine:read', 'usine:write'])]
    public ?string $nom = null;
}

Possible Solution

The issue seems to come from the processor’s return. Would it be possible, as an improvement, to have it return null when it is a DELETE operation?

ApiPlatform\State\Processor\ObjectMapperProcessor line 62

return $this->objectMapper->map(
    // persist the entity
    $persisted,
    $operation->getClass()
);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions