Hi guys! I've found a strange behavior. I have two related entities (I use their shortened versions here) and, as I mentioned in this issue, I use @Assert\NotBlank() for embedded entity validation. It used to work well.
<?php
namespace AppBundle\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
/**
* System.
*
* @ApiResource(attributes={
* "filters"={"system.search", "autocomplete_system.search"},
* "denormalization_context"={"groups"={"system_mutable"}},
* "normalization_context"={"groups"={"system_list"}},
* },
* itemOperations={
* "get"={
* "method"="GET",
* "normalization_context"={"groups"={"system_list"}}
* },
* "delete"={"method"="DELETE"},
* "put" = {
* "method"="PUT",
* "denormalization_context"={"groups"={"system_mutable"}},
* "validation_groups"={"system_valid"}
* }
* }
* )
*
* @ORM\Table(name="system")
*/
class System
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @Assert\NotBlank(groups={"system_valid"})
* @Groups({"system_list", "system_mutable"})
* @ORM\Column(type="string", length=255, unique=true, nullable=true)
*/
private $serialNumber;
/**
* @Assert\NotBlank(groups={"system_valid"})
*
* @Groups({"dashboard", "system_list", "customer_list", "customer_mutable", "system_mutable"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Part", mappedBy="system", cascade={"persist"})
*/
private $parts;
// Getters and setters (work well)
}
and
<?php
namespace AppBundle\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Part.
*
* @ApiResource(attributes={
* "filters"={"part.search"},
* "normalization_context"={"groups"={"part_list"}},
* "denormalization_context"={"groups"={"part_mutable"}}
* },
* itemOperations={
* "get"={"method"="GET"},
* "delete"={"method"="DELETE"},
* "put" = {
* "method"="PUT",
* "denormalization_context"={"groups"={"part_mutable"}},
* "validation_groups"={"part_valid"}
* }
* }
* )
*
* @ORM\Table(name="part")
*/
class Part
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @Assert\NotBlank(groups={"part_valid", "system_valid"})
* @Groups({"part_mutable", "part_list", "system_list", "system_mutable"})
* @ORM\Column(name="name", type="string", length=255, nullable=true)
*/
private $name;
/**
* @var string
*
* @Assert\NotBlank(groups={"part_valid", "system_valid"})
* @Groups({"part_mutable", "part_list", "system_list", "system_mutable"})
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $partNumber;
// Getters and setters etc.
}
But now I can easily send PUT request with embedded part without required partNumber and part entity will be successfully updated without any validation errors!! Example of PUT to /systems/36:
{
"serialNumber": "e-1111",
"parts": [
{
"@id": "/api/parts/8689",
"name": "Part 8689"
}
]
}
When I try to save invalid system or part, when they not embedded - validation works! I updated API Platform to the latest version, but it doesn't help! Waiting for your feedback
For parts, you should use the Valid consraint with traverse=true.
But group support for this constraint will be only for Symfony 3.4
@pierre-H Thanks, I've updated Symfony to 3.4 and @Assert\Valid now works perfectly with groups!
With pleasure !
Hello again! My celebration for Valid() working was short:)
It really works well but only for one level of embeddance! And yes, I used it with traverse=true (though now it is true by default)
Not sure, if the problem is on side of API Platform or at Symfony 3.4
What do you mean by
It really works well but only for one level of embeddance
?
If I have System entity and Parts in it - validation errors will be thrown
But if i have Contract, and have Systems in it, and Parts in each System (and they all have common validation_group) - Parts wouldn't be validated
If I have Customer -> Contracts -> Systems -> Parts, then Systems and Parts wouldn't be validated
So it works only for one level of embeddance
And there is the valid constraint in the contract entity at the system field ?
Yes, of course
And other system fields constraints work when you valid contract ?
Yes
That's strange ...
If groups are correct, it should work.
I think it's more a Symfony than an AP problem
...
OK, I will try to make pure Symfony 3.4 project and reproduce this problem on it
Reproduced and created an issue
Great debugging work, thanks! Closing here because it's now a Symfony bug.
Most helpful comment
For
parts, you should use the Valid consraint withtraverse=true.But group support for this constraint will be only for Symfony 3.4