Core: Validation of subresource doesn't seem to work

Created on 15 Sep 2017  路  14Comments  路  Source: api-platform/core

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

Most helpful comment

All 14 comments

@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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dunglas picture dunglas  路  79Comments

teohhanhui picture teohhanhui  路  40Comments

danaki picture danaki  路  24Comments

Simperfit picture Simperfit  路  24Comments

dunglas picture dunglas  路  25Comments