无法验证集合字段值的汇总

时间:2018-03-31 20:52:39

标签: php symfony validation

收据实体包含一组票证。每张票都有$amount属性。目前尚无法将票数之和限制为大于或等于0。

请注意,最初创建的收据没有任何票证。然后在javascript对话框中由TicketController在给定收据中添加/编辑故障单。

通过调试我发现调用Constraint但未调用ConstraintValidator

根据我对此similar SO question的接受答案:

编辑控制器:

    public function editTicketAction(Request $request, ReceiptTotal $rcptTotal, $id)
    {
        $em = $this->getDoctrine()->getManager();
        $ticket = $em->getRepository('AppBundle:Ticket')->find($id);
        $receipt = $ticket->getReceipt();
        $total = $rcptTotal->getReceiptTotal($receipt);
        $form = $this->createForm(TicketType::class, $ticket,
            [
                'validation_groups' => ['edit'],
                'cancel_action' => $this->generateUrl('homepage'),
                'rcptTotal' => $total,
        ]);
        $form->handleRequest($request);
...
    }

$total = $rcptTotal->getReceiptTotal($receipt);通过服务提供当前的门票总数。

表单构建器包括:

use AppBundle\Validator\Constraints\NonNegative;
...
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
...
        $form->add(
            'amount', TextType::class,
            [
                'label' => 'Amount',
                'label_attr' => ['style' => 'color: red;'],
                'constraints' => [
                    new NonNegative(['rcptTotal' => $options['rcptTotal']])
                ]
                ]
        );

约束&验证

class NonNegative extends Constraint
{
    protected $rcptTotal;

    public function __construct($options)
    {
        $this->rcptTotal = $options['rcptTotal'];
    }

    public $message = 'Receipt total may not be less than zero';

    public function validatedBy()
    {
        return get_class($this) . 'Validator';
    }

    public function getRcptTotal()
    {
        return $this->rcptTotal();
    }

}


class NonNegativeValidator extends ConstraintValidator
{

    public function validate($amount, Constraint $constraint)
    {
        $total = $contraint->getRcptTotal() + $amount;

        if ($total < 0) {
            $this->context->buildViolation($constraint->message)
                ->addViolation();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

它需要实体验证回调和故障单属性的组合。该属性为$rcptTotal,设置为给定收据的总票数。

TicketType表单修改:

->add(
    'amount', TextType::class,
    [
        'label' => 'Amount',
        'label_attr' => ['style' => 'color: red;'],
    ]
)
->add('rcptTotal', HiddenType::class, [
    'data' => $options['rcptTotal'],
    ])
...

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Ticket::class,
            'validation_groups' => [],
            'required' => false,
            'rcptTotal' => null,
        ));
    }

添加票证实体:

/**
 * @Assert\Callback(groups={"edit"})
 */
public function validateEdit(ExecutionContextInterface $context)
{
    $receipt = $this->getReceipt();
    $total = 0;
    $tickets = $receipt->getTickets();
    foreach ($tickets as $value) {
        $total += ($this->getId() !== $value->getId()) ? $value->getAmount() : $this->getAmount();
    }
    if (0 > $total) {
        $context->buildViolation('Receipt total may not be < 0!')
            ->atPath('amount')
            ->addViolation();
    }
}

/**
 * @Assert\Callback(groups={"add"})
 */
public function validateAdd(ExecutionContextInterface $context)
{
    $total = $this->getRcptTotal();
    if (0 > $total + $this->getAmount()) {
        $context->buildViolation('Receipt total may not be < 0!')
            ->atPath('amount')
            ->addViolation();
    }
}

private $rcptTotal;

public function setRcptTotal($rcptTotal)
{
    $this->rcptTotal = $rcptTotal;
}

public function getRcptTotal()
{
    return $this->rcptTotal;
}

票务管理员修改:

public function addTicketAction(Request $request, TicketArtist $owner, ReceiptTotal $rcptTotal, $id)
{
    $em = $this->getDoctrine()->getManager();
    $receipt = $em->getRepository('AppBundle:Receipt')->findOneBy(['id' => $id]);
    $total = $rcptTotal->getReceiptTotal($receipt);
    $ticket = new Ticket();
    $form = $this->createForm(TicketType::class, $ticket,
        [
            'validation_groups' => ['add'],
            'cancel_action' => $this->generateUrl('homepage'),
            'rcptTotal' => $total,
    ]);
...
}


public function editTicketAction(Request $request, $id)
{
    $em = $this->getDoctrine()->getManager();
    $ticket = $em->getRepository('AppBundle:Ticket')->find($id);
    $form = $this->createForm(TicketType::class, $ticket,
        [
            'validation_groups' => ['edit'],
            'cancel_action' => $this->generateUrl('homepage'),
    ]);
    $form->handleRequest($request);
...
}
相关问题