如何验证Symfony表单输入MoneyType?

时间:2016-07-05 16:33:51

标签: php forms validation symfony

如何使用MoneyType Field验证表单帖子?

it uses input type="text" instead of type="number"已经够糟糕了,但更糟糕的是输入的内容并不重要,比如“asdf”,响应始终是:valid form posted.我怎样才能有用错误消息指示用户他们需要存入有效的金额,例如“43.21”

我在添加选项上尝试了'error_bubbling' => true,在树枝视图中尝试了{{ form_errors(form) }},在this answer建议的控制器中尝试了$form->getErrors(),但这些都是空的,因为没有无论如何,$form->isValid()总是返回true,无论用户输入如何。

项目结构:

.
├── composer.json
├── composer.lock
├── pub
│   └── scratch.php
├── vendor
│   └── ...
└── views
    └── form.html.twig

scratch.php

<?php require_once __DIR__.'/../vendor/autoload.php';
use Symfony\Component\Form\Forms;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Translation\Translator;
use Symfony\Bridge\Twig\Form\TwigRenderer;
use Symfony\Bridge\Twig\Form\TwigRendererEngine;
use Symfony\Bridge\Twig\Extension\FormExtension;
use Symfony\Bridge\Twig\Extension\TranslationExtension;

// the Twig file that holds all the default markup for rendering forms
// this file comes with TwigBridge
$defaultFormTheme = 'form_div_layout.html.twig';

$appVariableReflection = new \ReflectionClass('\Symfony\Bridge\Twig\AppVariable');
$vendorTwigBridgeDir = dirname($appVariableReflection->getFileName());
// the path to your other templates
$viewsDir = realpath(__DIR__.'/../views');

$twig = new Twig_Environment(new Twig_Loader_Filesystem(array(
    $viewsDir,
    $vendorTwigBridgeDir.'/Resources/views/Form',
)));
$formEngine = new TwigRendererEngine(array($defaultFormTheme));

$twig->addExtension(
    new FormExtension(new TwigRenderer($formEngine))
);

$twig->addExtension(
    new TranslationExtension(new Translator('en'))
);

$formEngine->setEnvironment($twig);

// create your form factory as normal
$formFactory = Forms::createFormFactoryBuilder()
    ->addExtension(new HttpFoundationExtension())
    ->getFormFactory();

$formBuilder = $formFactory->createBuilder();

$formBuilder->add("amount", MoneyType::class, [
  'currency' => 'USD',
  'error_bubbling' => true
]);

$form = $formBuilder->getForm();

$request = Request::createFromGlobals();

$form->handleRequest($request);

if ($form->isValid()) {

    die('valid form posted.');

}

$form->getErrors(true);

echo $twig->render('form.html.twig', array(
    'form' => $form->createView(),
));

form.html.twig

{{ form_start(form) }}

    {{ form_errors(form) }}

    {{ form_widget(form) }}

    <input type="submit" />

{{ form_end(form) }}

composer.json

{
    "require": {
        "symfony/form": "^3.1",
        "symfony/twig-bridge": "^3.1",
        "symfony/translation": "^3.1",
        "symfony/http-foundation": "^3.1"
    }
}

2 个答案:

答案 0 :(得分:0)

您必须将一个或多个约束附加到您的表单字段,如下所示:

use Symfony\Component\Validator\Constraints\Regex;

$formBuilder->add("amount", MoneyType::class, [
  'currency' => 'USD',
  'error_bubbling' => true,
  'constraints' => [
    new Regex(array('pattern'=>'/\d+(\.\d+)?/','message'=>'must be numeric')),
  ]
]);

然后,如果违反约束,将显示“必须是数字”消息,并且您的表单无效。

内置约束定义如下: http://symfony.com/doc/current/reference/constraints.html

此处说明了验证用法: http://symfony.com/doc/current/book/forms.html#using-a-form-without-a-class

答案 1 :(得分:0)

我发现我错过了Validator component

use Symfony\Component\Validator\Validation;

// Set up the Validator component
$validator = Validation::createValidator();

然后我需要将validator extension添加到表单工厂。

use Symfony\Component\Form\Extension\Validator\ValidatorExtension;

// create your form factory as normal
$formFactory = Forms::createFormFactoryBuilder()
    ...
    ->addExtension(new ValidatorExtension($validator))
    ...

这当然需要composer require symfony/validator

所以,我 需要

  • $form->getErrors(true)
  • 'error_bubbling' => true
  • {{ form_errors(form) }}

scratch.php

<?php require_once __DIR__.'/../vendor/autoload.php';
use Symfony\Component\Form\Forms;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension;
use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Translation\Translator;
use Symfony\Component\Validator\Validation;
use Symfony\Bridge\Twig\Form\TwigRenderer;
use Symfony\Bridge\Twig\Form\TwigRendererEngine;
use Symfony\Bridge\Twig\Extension\FormExtension;
use Symfony\Bridge\Twig\Extension\TranslationExtension;

// the Twig file that holds all the default markup for rendering forms
// this file comes with TwigBridge
$defaultFormTheme = 'form_div_layout.html.twig';

$appVariableReflection = new \ReflectionClass('\Symfony\Bridge\Twig\AppVariable');
$vendorTwigBridgeDir = dirname($appVariableReflection->getFileName());
// the path to your other templates
$viewsDir = realpath(__DIR__.'/../views');

$twig = new Twig_Environment(new Twig_Loader_Filesystem(array(
    $viewsDir,
    $vendorTwigBridgeDir.'/Resources/views/Form',
)));
$formEngine = new TwigRendererEngine(array($defaultFormTheme));

$twig->addExtension(
    new FormExtension(new TwigRenderer($formEngine))
);

$twig->addExtension(
    new TranslationExtension(new Translator('en'))
);

$formEngine->setEnvironment($twig);

// Set up the Validator component
$validator = Validation::createValidator();

// create your form factory as normal
$formFactory = Forms::createFormFactoryBuilder()
    ->addExtension(new HttpFoundationExtension())
    ->addExtension(new ValidatorExtension($validator))
    ->getFormFactory();

$formBuilder = $formFactory->createBuilder();

$formBuilder->add("amount", MoneyType::class, [
  'currency' => 'USD'
]);

$form = $formBuilder->getForm();

$request = Request::createFromGlobals();

$form->handleRequest($request);

if ($form->isValid()) {

    die('valid form posted.');

}

$form->getErrors(true);

echo $twig->render('form.html.twig', array(
    'form' => $form->createView(),
));

form.html.twig

{{ form_start(form) }}

    {{ form_widget(form) }}

    <input type="submit" />

{{ form_end(form) }}

composer.json

{
    "require": {
        "symfony/form": "^3.1",
        "symfony/twig-bridge": "^3.1",
        "symfony/translation": "^3.1",
        "symfony/http-foundation": "^3.1"
        "symfony/validator": "^3.1"
    }
}