Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

The First Validation Constraints

The First Validation Constraints

~14 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

Chapter 16 showed: the API CURRENTLY accepts any syntactically valid JSON – a Project with an EMPTY name gets saved WITHOUT ISSUE. That changes NOW with the EXACT same Symfony Validator constraints from the Symfony course (chapter 22).

Adding #[NotBlank] and #[Length]

api/src/Entity/Project.php
<?php

declare(strict_types=1);

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use App\Repository\ProjectRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

#[ApiResource]
#[ORM\Entity(repositoryClass: ProjectRepository::class)]
class Project
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    #[Assert\NotBlank]
    #[Assert\Length(min: 3, max: 255)]
    private string $name = '';

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $description = null;

    #[ORM\Column]
    private \DateTimeImmutable $createdAt;

    // ... getters/setters unchanged
}

EXACTLY the same attributes as with normal Symfony form validation – use Symfony\Component\Validator\Constraints as Assert; is the USUAL import alias, to write Assert\NotBlank instead of the FULL class name.

Testing the validation

curl -k -i -X POST https://localhost/api/projects \
  -H 'Content-Type: application/json' \
  -d '{"name": ""}'
HTTP/2 422

{
  "@context": "/api/contexts/ConstraintViolationList",
  "@type": "ConstraintViolationList",
  "hydra:title": "An error occurred",
  "hydra:description": "name: This value should not be blank.\nname: This value is too short. It should have 3 characters or more.",
  "violations": [
    {"propertyPath": "name", "message": "This value should not be blank."},
    {"propertyPath": "name", "message": "This value is too short. It should have 3 characters or more."}
  ]
}

Status 422 Unprocessable Entity instead of 201 Created – EXACTLY the status code already previewed in the overview table from chapter 16. BOTH constraints fail SIMULTANEOUSLY and BOTH appear in the violations array.

Sending valid data

curl -k -i -X POST https://localhost/api/projects \
  -H 'Content-Type: application/json' \
  -d '{"name": "Website Relaunch"}'

Responds with 201 Created AGAIN – validation runs AUTOMATICALLY BEFORE saving, WITHOUT us having to call $validator->validate() ANYWHERE OURSELVES.

Tipp: Validation runs EQUALLY on POST, PUT, AND PATCH – for PATCH, ALL fields get checked (even those NOT included in the request body), not just the ones actually changed.