以 symfony 形式预先设置集合并只保存不空
Pre set collection in symfony form and save only not empties
我有星期和工作日。我需要用所有可能的 WeekDays(星期一午餐、星期一晚餐、星期二午餐、星期二晚餐等)编辑一周,即使它们没有保留。
周:
<?php
namespace App\Entity;
use App\Repository\WeekRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass=WeekRepository::class)
*/
class Week
{
/**
* @ORM\Id
* @ORM\Column(type="uuid", unique=true)
*/
private Uuid $id;
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank(message="Merci de donner un nom à votre semaine type.")
* @Assert\Length(max=255, maxMessage="Le nom de votre semaine type ne peut pas faire plus de 255 caractères.")
*/
private ?string $name;
/**
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="weeks")
* @ORM\JoinColumn(nullable=false)
*/
private ?User $user;
/**
* @ORM\OneToMany(targetEntity=WeekDay::class, mappedBy="week", orphanRemoval=true, cascade={"persist"})
*/
private Collection $days;
public function __construct()
{
$this->id = Uuid::v6();
$this->days = new ArrayCollection();
}
public function getId(): Uuid
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(?string $name): self
{
$this->name = $name;
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
public function hasDay(WeekDay $checkday): bool
{
foreach ($this->getDays() as $day) {
if (
$day->getDay() === $checkday->getDay() &&
$day->getTime() === $checkday->getTime()
) {
return true;
}
}
return false;
}
public function getDays(): Collection
{
return $this->days;
}
public function addDay(WeekDay $day): void
{
if (!$this->hasDay($day)) {
$this->days[$day->getDay().$day->getTime()] = $day;
$day->setWeek($this);
}
}
public function removeDay(WeekDay $day): void
{
$this->days->removeElement($day);
$day->setWeek(null);
}
}
工作日:
<?php
namespace App\Entity;
use App\Repository\WeekDayRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;
/**
* @ORM\Entity(repositoryClass=WeekDayRepository::class)
*/
class WeekDay
{
private const MONDAY = 1;
private const TUESDAY = 2;
private const WEDNESDAY = 3;
private const THURSDAY = 4;
private const FRIDAY = 5;
private const SATURDAY = 6;
private const SUNDAY = 7;
private const TIME_LUNCH = 1;
private const TIME_DINNER = 2;
/**
* @ORM\Id
* @ORM\Column(type="uuid", unique=true)
*/
private Uuid $id;
/**
* @ORM\Column(type="integer")
*/
private int $day;
/**
* @ORM\Column(type="integer")
*/
private int $time;
/**
* @ORM\Column(type="boolean")
*/
private bool $used = false;
/**
* @ORM\ManyToOne(targetEntity=Week::class, inversedBy="days")
* @ORM\JoinColumn(nullable=false)
*/
private ?Week $week;
/**
* @ORM\ManyToMany(targetEntity=Theme::class)
*/
private Collection $themes;
/**
* @ORM\Column(type="array", nullable=true)
*/
private array $preparations = [];
public function __construct()
{
$this->id = Uuid::v6();
$this->themes = new ArrayCollection();
}
public function getId(): Uuid
{
return $this->id;
}
public function getDay(): ?int
{
return $this->day;
}
public function setDay(int $day): self
{
$this->day = $day;
return $this;
}
public static function getDays(): array
{
return [
self::MONDAY => 'monday',
self::TUESDAY => 'tuesday',
self::WEDNESDAY => 'wednesday',
self::THURSDAY => 'thursday',
self::FRIDAY => 'friday',
self::SATURDAY => 'saturday',
self::SUNDAY => 'sunday',
];
}
public function getDayLabel()
{
$labels = self::getDays();
return $labels[$this->getDay()] ?? '-';
}
public function getTime(): ?int
{
return $this->time;
}
public function setTime(int $time): self
{
$this->time = $time;
return $this;
}
public static function getTimes(): array
{
return [
self::TIME_LUNCH => 'lunch',
self::TIME_DINNER => 'dinner',
];
}
public function getTimeLabel()
{
$labels = self::getTimes();
return $labels[$this->getTime()] ?? '-';
}
public function isUsed(): bool
{
return $this->used;
}
public function setUsed(bool $used): self
{
$this->used = $used;
return $this;
}
public function getWeek(): ?Week
{
return $this->week;
}
public function setWeek(?Week $week): self
{
$this->week = $week;
return $this;
}
}
我的实际形态:
class WeekType extends AbstractType
{
private WeekService $service;
public function __construct(WeekService $service)
{
$this->service = $service;
}
/** {@inheritdoc} **/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('days', CollectionType::class, [
'entry_type' => WeekDayType::class,
'by_reference' => false,
'allow_add' => true,
'allow_delete' => true,
'data' => $this->service->getAllSortedDays($builder->getData()),
])
;
$builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
$form = $event->getForm();
$data = $event->getForm()->getData();
$form
->add('days', CollectionType::class, [
'entry_type' => WeekDayType::class,
'by_reference' => false,
'allow_add' => true,
'allow_delete' => true,
'data' => $this->service->getAllSortedDays($data),
])
;
});
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Week::class,
]);
}
}
获取所有排序日期的方法:
public function getAllSortedDays(Week $week): Collection
{
$weekDays = WeekDay::getDays();
$times = WeekDay::getTimes();
foreach (array_keys($weekDays) as $dayId) {
foreach (array_keys($times) as $timeId) {
$weekDay = (new WeekDay())
->setDay($dayId)
->setTime($timeId)
;
$week->addDay($weekDay);
}
}
$orderBy = (Criteria::create())->orderBy([
'day' => Criteria::ASC,
'time' => Criteria::ASC,
]);
return $week->getDays()->matching($orderBy);
}
现在,页面加载的表单没问题,我得到了所有的工作日。
我订阅了 SUBMIT 事件以在提交时显示所有工作日:如果我不这样做,我只提交了工作日。
现在的问题是,如果我这样提交,它会保存所有的 WeekDays,甚至是空的,我宁愿避免它。
我删除了 allow_delete 选项,这样我就可以使用 SUBMIT 事件,默认清空对象不再自动删除。
所以如果表格有错误我会得到它们,但我必须在 POST_SUBMIT 事件中手动删除它们以避免持久性。
$builder
->add('name')
->add('days', CollectionType::class, [
'entry_type' => WeekDayType::class,
'by_reference' => false,
'data' => $this->service->getAllSortedDays($builder->getData()),
])
;
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
$data = $event->getForm()->getData();
foreach ($data->getDays() as $day) {
if (
false === $day->isUsed() &&
0 === count($day->getThemes()) &&
0 === count($day->getPreparations())
) {
$data->removeDay($day);
}
}
});
我有星期和工作日。我需要用所有可能的 WeekDays(星期一午餐、星期一晚餐、星期二午餐、星期二晚餐等)编辑一周,即使它们没有保留。
周:
<?php
namespace App\Entity;
use App\Repository\WeekRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass=WeekRepository::class)
*/
class Week
{
/**
* @ORM\Id
* @ORM\Column(type="uuid", unique=true)
*/
private Uuid $id;
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank(message="Merci de donner un nom à votre semaine type.")
* @Assert\Length(max=255, maxMessage="Le nom de votre semaine type ne peut pas faire plus de 255 caractères.")
*/
private ?string $name;
/**
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="weeks")
* @ORM\JoinColumn(nullable=false)
*/
private ?User $user;
/**
* @ORM\OneToMany(targetEntity=WeekDay::class, mappedBy="week", orphanRemoval=true, cascade={"persist"})
*/
private Collection $days;
public function __construct()
{
$this->id = Uuid::v6();
$this->days = new ArrayCollection();
}
public function getId(): Uuid
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(?string $name): self
{
$this->name = $name;
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
public function hasDay(WeekDay $checkday): bool
{
foreach ($this->getDays() as $day) {
if (
$day->getDay() === $checkday->getDay() &&
$day->getTime() === $checkday->getTime()
) {
return true;
}
}
return false;
}
public function getDays(): Collection
{
return $this->days;
}
public function addDay(WeekDay $day): void
{
if (!$this->hasDay($day)) {
$this->days[$day->getDay().$day->getTime()] = $day;
$day->setWeek($this);
}
}
public function removeDay(WeekDay $day): void
{
$this->days->removeElement($day);
$day->setWeek(null);
}
}
工作日:
<?php
namespace App\Entity;
use App\Repository\WeekDayRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;
/**
* @ORM\Entity(repositoryClass=WeekDayRepository::class)
*/
class WeekDay
{
private const MONDAY = 1;
private const TUESDAY = 2;
private const WEDNESDAY = 3;
private const THURSDAY = 4;
private const FRIDAY = 5;
private const SATURDAY = 6;
private const SUNDAY = 7;
private const TIME_LUNCH = 1;
private const TIME_DINNER = 2;
/**
* @ORM\Id
* @ORM\Column(type="uuid", unique=true)
*/
private Uuid $id;
/**
* @ORM\Column(type="integer")
*/
private int $day;
/**
* @ORM\Column(type="integer")
*/
private int $time;
/**
* @ORM\Column(type="boolean")
*/
private bool $used = false;
/**
* @ORM\ManyToOne(targetEntity=Week::class, inversedBy="days")
* @ORM\JoinColumn(nullable=false)
*/
private ?Week $week;
/**
* @ORM\ManyToMany(targetEntity=Theme::class)
*/
private Collection $themes;
/**
* @ORM\Column(type="array", nullable=true)
*/
private array $preparations = [];
public function __construct()
{
$this->id = Uuid::v6();
$this->themes = new ArrayCollection();
}
public function getId(): Uuid
{
return $this->id;
}
public function getDay(): ?int
{
return $this->day;
}
public function setDay(int $day): self
{
$this->day = $day;
return $this;
}
public static function getDays(): array
{
return [
self::MONDAY => 'monday',
self::TUESDAY => 'tuesday',
self::WEDNESDAY => 'wednesday',
self::THURSDAY => 'thursday',
self::FRIDAY => 'friday',
self::SATURDAY => 'saturday',
self::SUNDAY => 'sunday',
];
}
public function getDayLabel()
{
$labels = self::getDays();
return $labels[$this->getDay()] ?? '-';
}
public function getTime(): ?int
{
return $this->time;
}
public function setTime(int $time): self
{
$this->time = $time;
return $this;
}
public static function getTimes(): array
{
return [
self::TIME_LUNCH => 'lunch',
self::TIME_DINNER => 'dinner',
];
}
public function getTimeLabel()
{
$labels = self::getTimes();
return $labels[$this->getTime()] ?? '-';
}
public function isUsed(): bool
{
return $this->used;
}
public function setUsed(bool $used): self
{
$this->used = $used;
return $this;
}
public function getWeek(): ?Week
{
return $this->week;
}
public function setWeek(?Week $week): self
{
$this->week = $week;
return $this;
}
}
我的实际形态:
class WeekType extends AbstractType
{
private WeekService $service;
public function __construct(WeekService $service)
{
$this->service = $service;
}
/** {@inheritdoc} **/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('days', CollectionType::class, [
'entry_type' => WeekDayType::class,
'by_reference' => false,
'allow_add' => true,
'allow_delete' => true,
'data' => $this->service->getAllSortedDays($builder->getData()),
])
;
$builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
$form = $event->getForm();
$data = $event->getForm()->getData();
$form
->add('days', CollectionType::class, [
'entry_type' => WeekDayType::class,
'by_reference' => false,
'allow_add' => true,
'allow_delete' => true,
'data' => $this->service->getAllSortedDays($data),
])
;
});
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Week::class,
]);
}
}
获取所有排序日期的方法:
public function getAllSortedDays(Week $week): Collection
{
$weekDays = WeekDay::getDays();
$times = WeekDay::getTimes();
foreach (array_keys($weekDays) as $dayId) {
foreach (array_keys($times) as $timeId) {
$weekDay = (new WeekDay())
->setDay($dayId)
->setTime($timeId)
;
$week->addDay($weekDay);
}
}
$orderBy = (Criteria::create())->orderBy([
'day' => Criteria::ASC,
'time' => Criteria::ASC,
]);
return $week->getDays()->matching($orderBy);
}
现在,页面加载的表单没问题,我得到了所有的工作日。
我订阅了 SUBMIT 事件以在提交时显示所有工作日:如果我不这样做,我只提交了工作日。
现在的问题是,如果我这样提交,它会保存所有的 WeekDays,甚至是空的,我宁愿避免它。
我删除了 allow_delete 选项,这样我就可以使用 SUBMIT 事件,默认清空对象不再自动删除。
所以如果表格有错误我会得到它们,但我必须在 POST_SUBMIT 事件中手动删除它们以避免持久性。
$builder
->add('name')
->add('days', CollectionType::class, [
'entry_type' => WeekDayType::class,
'by_reference' => false,
'data' => $this->service->getAllSortedDays($builder->getData()),
])
;
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
$data = $event->getForm()->getData();
foreach ($data->getDays() as $day) {
if (
false === $day->isUsed() &&
0 === count($day->getThemes()) &&
0 === count($day->getPreparations())
) {
$data->removeDay($day);
}
}
});