API Platform version(s) affected: 4.2.12
Description
A PUT operation with multiple URI variables does not seem to work in any way.
How to reproduce
Imagine the following API resource:
#[ApiResource(
shortName: 'Device',
operations: [
new Put(
uriTemplate: '/users/{userId}/devices/{id}',
uriVariables: [
'userId' => new Link(
toProperty: 'user',
fromClass: UserEntity::class,
),
'id' => new Link(
fromClass: DeviceEntity::class,
),
],
input: PutDeviceDto::class,
allowCreate: true,
),
],
stateOptions: new Options(entityClass: DeviceEntity::class)
)]
#[Map(source: DeviceEntity::class)]
final class DeviceResource
{
public Uuid $id;
}
Within the PersistProcessor, we have the following snippet of code:
foreach (array_reverse($links) as $link) {
if ($link->getExpandedValue() || !$link->getFromClass()) {
continue;
}
$identifierProperties = $link->getIdentifiers();
$hasCompositeIdentifiers = 1 < \count($identifierProperties);
foreach ($identifierProperties as $identifierProperty) {
$reflectionProperty = $reflectionProperties[$identifierProperty];
$reflectionProperty->setValue($newData, $this->getIdentifierValue($identifiers, $hasCompositeIdentifiers ? $identifierProperty : null));
}
}
This will set the value from the actual URL onto the object. There's a few things I found and tried:
$link->getIdentifiers() always returns id by default, meaning it'll actually never set the value for the user/userId
- When providing the
identifiers parameter with value ['user'] to the userId Link it'll not take into account that the user variable within my entity needs to be an object of User, not a UUID or int.
- When providing the
identifiers parameter with value ['userId'] to the userId Link it'll just not be able to find that property on the entity, as it does not exist. Which makes sense, since it's a relational object user instead of just the ID userId
No matter what I tried, I end up with the following SQL error:
An exception occurred while executing a query: SQLSTATE[23502]: Not null violation: 7 ERROR: null value in column \"user_id\" of relation \"device\" violates not-null constraint\nDETAIL: Failing row contains (3, null).
Here's a repo where you can debug the issue yourself: https://github.com/Kyzegs/api-platform/tree/bug-put-overwriting-identifier
API Platform version(s) affected: 4.2.12
Description
A
PUToperation with multiple URI variables does not seem to work in any way.How to reproduce
Imagine the following API resource:
#[ApiResource( shortName: 'Device', operations: [ new Put( uriTemplate: '/users/{userId}/devices/{id}', uriVariables: [ 'userId' => new Link( toProperty: 'user', fromClass: UserEntity::class, ), 'id' => new Link( fromClass: DeviceEntity::class, ), ], input: PutDeviceDto::class, allowCreate: true, ), ], stateOptions: new Options(entityClass: DeviceEntity::class) )] #[Map(source: DeviceEntity::class)] final class DeviceResource { public Uuid $id; }Within the
PersistProcessor, we have the following snippet of code:This will set the value from the actual URL onto the object. There's a few things I found and tried:
$link->getIdentifiers()always returnsidby default, meaning it'll actually never set the value for theuser/userIdidentifiersparameter with value['user']to theuserIdLinkit'll not take into account that theuservariable within my entity needs to be an object ofUser, not aUUIDorint.identifiersparameter with value['userId']to theuserIdLinkit'll just not be able to find that property on the entity, as it does not exist. Which makes sense, since it's a relational objectuserinstead of just the IDuserIdNo matter what I tried, I end up with the following SQL error:
Here's a repo where you can debug the issue yourself: https://github.com/Kyzegs/api-platform/tree/bug-put-overwriting-identifier