symfony 如何在表单域上添加动态约束

ca1c2owp  于 2023-02-24  发布在  其他
关注(0)|答案(1)|浏览(155)

我的“Session”实体中有一个非必填字段,字段名为“location”。我希望仅当另一个字段等于true时才将其设置为必填字段,该属性名为“isVirtual
我以为我会用BeforeEntityUpdatedEvent事件创建一个eventSubscriber,但我不知道如何添加约束,也不确定何时触发此事件。
我尝试执行custom validation constraint,但不知道如何在ConstraintValidator类中获取“isVirtual”值。
我需要有人帮我寻找正确的方向。我把我的实体放在那里

<?php

namespace App\Entity;

use App\Repository\SessionRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

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

    #[ORM\Column]
    private ?\DateTimeImmutable $beginsAt = null;

    #[ORM\Column]
    private ?\DateTimeImmutable $endsAt = null;

    #[ORM\ManyToOne(inversedBy: 'sessions')]
    #[ORM\JoinColumn(nullable: false)]
    private ?Formation $formation = null;

    #[ORM\ManyToOne(inversedBy: 'sessions')]
    #[ORM\JoinColumn(nullable: true)]
    private ?Location $location = null;

    #[ORM\Column]
    private ?bool $isVirtual = null;

    #[ORM\OneToMany(mappedBy: 'session', targetEntity: UserSession::class)]
    private Collection $users;

    #[ORM\Column(nullable: true)]
    private ?int $numberOfSeats = null;

    public function __construct()
    {
        $this->users = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getBeginsAt(): ?\DateTimeImmutable
    {
        return $this->beginsAt;
    }

    public function setBeginsAt(\DateTimeImmutable $beginsAt): self
    {
        $this->beginsAt = $beginsAt;

        return $this;
    }

    public function getEndsAt(): ?\DateTimeImmutable
    {
        return $this->endsAt;
    }

    public function setEndsAt(\DateTimeImmutable $endsAt): self
    {
        $this->endsAt = $endsAt;

        return $this;
    }

    public function getFormation(): ?Formation
    {
        return $this->formation;
    }

    public function setFormation(?Formation $formation): self
    {
        $this->formation = $formation;

        return $this;
    }

    public function getLocation(): ?Location
    {
        return $this->location;
    }

    public function setLocation(?Location $location): self
    {
        $this->location = $location;

        return $this;
    }

    public function isIsVirtual(): ?bool
    {
        return $this->isVirtual;
    }

    public function setIsVirtual(bool $isVirtual): self
    {
        $this->isVirtual = $isVirtual;

        return $this;
    }

    /**
     * @return Collection<int, UserSession>
     */
    public function getUsers(): Collection
    {
        return $this->users;
    }

    public function addUser(UserSession $user): self
    {
        if (!$this->users->contains($user)) {
            $this->users->add($user);
            $user->setSession($this);
        }

        return $this;
    }

    public function removeUser(UserSession $user): self
    {
        if ($this->users->removeElement($user)) {
            // set the owning side to null (unless already changed)
            if ($user->getSession() === $this) {
                $user->setSession(null);
            }
        }

        return $this;
    }

    public function getNumberOfSeats(): ?int
    {
        return $this->numberOfSeats;
    }

    public function setNumberOfSeats(int $numberOfSeats): self
    {
        $this->numberOfSeats = $numberOfSeats;

        return $this;
    }

    public function retrieveSeat($number): self
    {
        $this->setNumberOfSeats($this->getNumberOfSeats() - $number);

        return $this;
    }

}

和EasyAdmin控制器

<?php

namespace App\Controller\Admin;

use App\Entity\Session;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField;
use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;

class SessionCrudController extends AbstractCrudController
{
    public static function getEntityFqcn(): string
    {
        return Session::class;
    }

    public function configureFields(string $pageName): iterable
    {
        return [
            IdField::new('id')->hideOnForm(),
            AssociationField::new('formation'),
            DateField::new('beginsAt'),
            DateField::new('endsAt'),
            BooleanField::new('isVirtual'),
            AssociationField::new('location')
                ->setRequired(false)
                ->setFormTypeOption('attr', ['placeholder' => 'Enter location']),
            IntegerField::new('numberOfSeats')
                ->setRequired(false)
        ];
    }    
}

先谢谢你了。

ppcbkaq5

ppcbkaq51#

下面是回调实现。

<?php

namespace App\Entity;

........
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;

class Session
{
     ........

    #[Assert\Callback]
    public function validate(ExecutionContextInterface $context, $payload)
    {   
        if (!$this->isIsVirtual()) {
            if ($this->getLocation() === null) {
                $context->buildViolation("Session needs a location when it's not virtual")
                    ->atPath('location')
                    ->addViolation();
            }
            if ($this->getNumberOfSeats() === null) {
                $context->buildViolation("Session needs a number of seats when it's not virtual")
                    ->atPath('numberOfSeats')
                    ->addViolation();
            }
        }
    }
}

相关问题