我偶然发现了一个关于S以及如何正确使用它们的问题。当我知道如何实现它们并将它们添加到我的表单字段时,我想知道DataTransformers应该如何与S组合。
下面的代码显示了我的用例。
形式
<?php
namespace AppBundle\Form;
use AppBundle\Form\DataTransformer\Consent\ConsentTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\IsTrue;
class ConsentTestForm extends AbstractType
{
/** @var ConsentTransformer $consentTransformer */
private $consentTransformer;
/**
* ConsentTestForm constructor.
* @param ConsentTransformer $consentTransformer
*/
public function __construct(ConsentTransformer $consentTransformer)
{
$this->consentTransformer = $consentTransformer;
}
/**
* @inheritDoc
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('accountConsent', CheckboxType::class, [
'constraints' => [
new IsTrue()
]
]);
$builder->get('accountConsent')->addModelTransformer($this->consentTransformer);
$builder->add('submit', SubmitType::class);
}
}模型
<?php
class User extends Concrete implements \Pimcore\Model\DataObject\DirtyIndicatorInterface
{
protected $accountConsent;
/**
* ...
*/
public function getAccountConsent () {
// ...
}
/**
* ...
*/
public function setAccountConsent ($accountConsent) {
// ...
}
}为了简洁起见,省略了许多代码。模型是一个Pimcore类。
The DataTransformer
<?php
namespace Passioneight\Bundle\FormBuilderBundle\Form\DataTransformer\Consent;
use Pimcore\Model\DataObject\Data\Consent;
use Symfony\Component\Form\DataTransformerInterface;
class ConsentTransformer implements DataTransformerInterface
{
/**
* @inheritDoc
* @param Consent|null $consent
*/
public function transform($consent)
{
return $consent instanceof Consent && $consent->getConsent();
}
/**
* @inheritDoc
* @param bool|null $consented
*/
public function reverseTransform($consented)
{
$consent = new Consent();
$consent->setConsent($consented ?: false);
return $consent;
}
}如您所见,任何提交的值(即
null、true、false)都将转换为Consent,反之亦然。
主计长
<?php
namespace AppBundle\Controller;
use AppBundle\Form\ConsentTestForm;
use AppBundle\Model\DataObject\User;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* Class TestController
* @package AppBundle\Controller
*
* @Route("/test")
*/
class TestController extends AbstractFrontendController
{
/**
* @Route("/form")
* @param Request $request
* @return Response
*/
public function formAction(Request $request)
{
$user = new User();
$form = $this->createForm(ConsentTestForm::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
p_r("VALID");
p_r($user);
} else {
p_r("NOT VALID");
}
};
return $this->renderTemplate(':Test:form.html.twig', [
"form" => $form->createView()
]);
}
}注意如何将
new User()作为实体传递,以便使用提交的值自动填充它。
视点
{{ form(form) }}问题
表单可以很好地构建,最终显示带有我指定标签的复选框。由于转换器,checked-state甚至被正确显示,因为transform方法将User的Consent转换为boolean。
然而,当提交表单时,会显示一个错误,说明需要帐户同意.虽然这在没有征得同意的情况下提交表单是很好的,但如果同意的话,这并不完全是理想的结果。
当同意时,提交的值将转换为Consent,后者将保存值true。但是,由于转换是在验证提交的值之前完成的,因此会显示前面提到的错误。之所以会发生这种情况,是因为表单中添加的accountConsent字段有一个Constraint集,即IsTrue。因此,IsTrueValidator验证Consent (而不是实际提交的值)。
显然,
IsTrueValidator不能知道Pimcore的Consent类。
问题
所有这些都给我留下了一个问题:如何将IsTrue**-constraint与** ConsentDataTransformer**?**恰当地结合在一起?
发布于 2020-04-08 11:51:32
验证的问题在于,您试图将对象验证为布尔类型。在提交表单时,总是在尝试验证和转换时执行约束。因此,您已经转换了数据,这就是为什么IsBool验证失败的原因,因为该值的类型是同意对象,而不是布尔值。
要解决这个问题,您必须创建覆盖IsTrue的新验证约束。
<?php
namespace App\Form\Validator;
use Symfony\Component\Validator\Constraints\IsTrue;
class IsConsented extends IsTrue
{
public $message = 'You need to consent!';
}以及同一名称空间上的验证器;
<?php
namespace App\Form\Validator;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\IsTrueValidator;
class IsConsentedValidator extends IsTrueValidator
{
public function validate($value, Constraint $constraint)
{
return parent::validate($value->getConsent(), $constraint);
}
}然后,您需要使用IsTrue更改IsConsented约束,如下所示;
<?php
namespace App\Form;
use App\Entity\User;
use App\Form\DataTransformer\ConsentTransformer;
use App\Form\Validator\IsConsented;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ConsentTestFormType extends AbstractType
{
/** @var ConsentTransformer $consentTransformer */
private $consentTransformer;
/**
* ConsentTestForm constructor.
* @param ConsentTransformer $consentTransformer
*/
public function __construct(ConsentTransformer $consentTransformer)
{
$this->consentTransformer = $consentTransformer;
}
/**
* @inheritDoc
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('accountConsent', CheckboxType::class, [
'constraints' => [
new IsConsented()
]
]);
$builder->get('accountConsent')->addModelTransformer($this->consentTransformer);
$builder->add('submit', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}就是这样。你的表格现在有效了。输出应该看起来像;
FormController.php on line 30:
"VALID"https://stackoverflow.com/questions/60789560
复制相似问题