Skip to content

PATCHing a subresource returns a "No route matches %s" error #3609

Description

@leup

API Platform version(s) affected: v2.5.6 (and before)

Description
When sending a PATCH request for a resource containing a subresource, the request fails with a "No route matches %s" error.
This is because the subresource is not found.

The culprit seems to be in the ItemNormalizer::updateObjectToPopulate.

https://github.com/api-platform/core/blob/master/src/Serializer/ItemNormalizer.php#L76

$context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getItemFromIri((string) $data['id'], $context + ['fetch_data' => true]);

It should be data['@id'] instead of $data['id'] when calling getItemFromIri

How to reproduce

Given a Resource entity with a subresource field of type Subresource entity on a OneToOne relationship.

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ApiResource()
 */
class Resource
{
    /**
     * @ORM\OneToOne(targetEntity=Subresource::class, cascade={"persist", "remove"})
     */
     private $resource;

    public function getSubresource(): ?Subresource
    {
        return $this->subresource;
    }

    public function setSubresource(?Subresource $subresource): self
    {
        $this->subresource = $subresource;
        return $this;
    }
}
namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ApiResource()
 */
class Subresource
{
    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
     private $someField;

    public function getSomeField(): ?string
    {
        return $this->someField;
    }

    public function setSomeField(?string $someField): self
    {
        $this->someField = $someField;
        return $this;
    }
}

Trying to send a PATCH request which will update the subresource (given that you already have created the resource + subresource first :D)

{
  "@id": "/api/resource/1",
  "subresource": {
     "@id": "/api/subresource/1",
     "someField": "someValue"
  }
}

Possible Solution

It should be data['@id'] instead of $data['id'] when calling getItemFromIri.
Tried it in local and the error goes away.

I am not confident of any side effect this "fix" could have as I am not a expert of the internals of Api Platform.

edit: typo

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions