我有一个面板来获取一些交易,用户可以选择月份和年份并获取该月份和年份的交易。问题是,如果你错误地选择了未来的日期,我会收到一个 sql 错误,因为未来那个月份的表显然不在数据库中。
如何在构建表单中使月份的 ChoiceType 和年份的 IntegerType 不允许用户选择当前月份之后的任何月份或年份?我试图用验证器来完成此操作,但不知道如何使其工作。
我的构建形式是这样的:
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$currentDate = $this->myDateTime->getNewDate();
$builder
->add('month', ChoiceType::class, [
'choices' => array_combine(range(1, 12), range(1, 12)),
'label' => 'Month:',
'required' => true,
'data' => $currentDate->format('m'),
'attr' => ['class' => 'form-control'],
'constraints' => [
new Assert\NotBlank(),
new Assert\Range([
'max' => ($currentDate->format('Y'))
? intval($currentDate->format('m'))
: 12,
'maxMessage' => 'Please select a valid month.',
]),
],
])
->add('year', IntegerType::class, [
'label' => 'Year:',
'required' => true,
'data' => $currentDate->format('Y'),
'attr' => ['class' => 'form-control'],
'constraints' => [
new Assert\NotBlank(),
new Assert\Range([
'max' => intval($currentDate->format('Y')),
'maxMessage' => 'Please select a valid year.',
]),
],
])
->add('submit', SubmitType::class, [
'label' => 'Search',
'attr' => ['class' => 'btn btn-primary ml-2'],
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => null,
]);
}
我有这个验证..但是你现在甚至不能选择1之后的一个月,甚至在2024年之前......而且你仍然可以选择2024年之后的任何一年..
我会创建一个自定义验证器。您需要自定义所选月份和年份是否为过去的逻辑。
您可以相应地删除表单定义中的约束定义。
搜索日期约束
namespace App\Validator;
use Symfony\Component\Validator\Constraint;
#[\Attribute]
class SearchDate extends Constraint
{
public function validatedBy(): string
{
return SearchDateValidator::class;
}
public function getTargets(): array|string
{
return self::CLASS_CONSTRAINT;
}
}
搜索日期验证器
namespace App\Validator;
use App\Entity\SearchFormEntity;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class SearchDateValidator extends ConstraintValidator
{
/**
* @param SearchFormEntity $value
* @param Constraint $constraint
*
* @return void
*/
public function validate($value, Constraint $constraint): void
{
$currentDate = new \DateTime(
(new \DateTime())->format('Y-m-1 00:00:00')
);
$formDate = new \DateTime();
$formDate->setDate(
$value->getYear(),
$value->getMonth(),
1
)->setTime(0, 0 , 0);
if ($formDate >= $currentDate) {
return;
}
$this->context->buildViolation(
'My error message'
)->addViolation();
}
}
搜索表单实体
您在类中定义 SearchDate 约束 (
#[SearchDate]
)。
namespace App\Entity;
use App\Validator\SearchDate;
#[SearchDate]
class SearchFormEntity
{
private string $month;
private string $year;
public function getMonth(): string
{
return $this->month;
}
public function setMonth(string $month): void
{
$this->month = $month;
}
public function getYear(): string
{
return $this->year;
}
public function setYear(string $year): void
{
$this->year = $year;
}
}
功能测试
use App\Entity\SearchFormEntity;
use App\Validator\SearchDate;
use App\Validator\SearchDateValidator;
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
class SearchDateValidatorTest extends ConstraintValidatorTestCase
{
public function createValidator(): SearchDateValidator
{
return new SearchDateValidator();
}
public function testMonthInFuture()
{
$entity = new SearchFormEntity();
$entity->setMonth('8');
$entity->setYear('2024');
$this->validator->validate($entity, new SearchDate());
$this->assertNoViolation();
}
public function testCurrentMonth()
{
$entity = new SearchFormEntity();
$entity->setMonth('1');
$entity->setYear('2024');
$this->validator->validate($entity, new SearchDate());
$this->assertNoViolation();
}
public function testMonthInPast()
{
$entity = new SearchFormEntity();
$entity->setMonth('12');
$entity->setYear('2023');
$this->validator->validate($entity, new SearchDate());
$this->buildViolation('My error message')
->assertRaised();
}
}