我继承了一个应用程序,但我还不是Symfony专家。该应用程序具有一个简单的用户实体(当然还有其他一些功能),并且具有一些独特的约束条件:
/**
* User
*
* @ORM\Table(name="users")
* @ORM\Entity
* @UniqueEntity(
* fields={"username", "school"},
* message="There's already a registered user with that login in this school."
* )
* @UniqueEntity(fields={"email"},
* message="That email is already registered")
* )
*/
在创建表单时,以及违反此类约束时,消息将显示在表单本身上,并且流程不会返回到控制器(完全可以)。
我有一个非ORM属性,带有$ plainPassword,它以表格形式保存输入的文本,以及通常的$ password保持加密的密码。这是此字段的表单部分:
$builder->add(
'plainPassword',
TextType::class,
[
'required' => false,
'attr' =>
[
'autocomplete' => 'off',
],
'error_bubbling' => true,
]
)
;
现在,对于密码,我有一个自定义验证器,可以在下一个功能中看到它:
public function isPasswordValid(string $p = null)
{
if (null==$p) {
$p = $this->getPlainPassword();
}
// If I'm not changing the password, there must be one previously
$success = strlen($this->getPassword())>0;
if (strlen($p)) {
$success = (strlen($p)>7 && preg_match('/[A-Za-z]/', $p) && preg_match('/[0-9]/', $p));
}
return $success;
}
此函数本身可以很好地工作,但是我想将其附加到表单,以便当plainPassword字段具有“无效”密码(即该函数返回false)时。因此,我尝试在函数之前使用注释块:
/**
* @Assert\IsTrue(message = "The password is not a valid password")
*/
public function isPasswordValid(string $p = null)
{
if (null==$p) {
$p = $this->getPlainPassword();
}
// If I'm not changing the password, there must be one previously
$success = strlen($this->getPassword())>0;
if (strlen($p)) {
$success = (strlen($p)>7 && preg_match('/[A-Za-z]/', $p) && preg_match('/[0-9]/', $p));
}
return $success;
}
消息进入form.errors,当以非特定方式(但不同)在非模式模式下调用表单时,我可以显示该消息,但是通过ajax的默认表单行为显示为弹出窗口甚至跳过这种行为,所以我没有收到此消息。然后,我尝试在表单的字段定义中使用error_mapping来链接属性和函数,但是结果是相同的(即,未显示)。
我什至尝试构建自定义验证器。在所有这些情况下,验证密码时的行为都可以,但是当密码无效时,不提交表单,但根本没有错误消息(与@UniqueConstraint中定义的其他字段不同)。因此,我取消了或者只是输入了一个有效的密码并提交了表单,但是用户没有关于错误的引用(并且探查器或开发日志没有显示任何有关此的内容,因此我必须弄清楚通过更改密码)。
因此,肯定有我缺少的东西,或者仅仅是通过我测试的手段是不可能的。我现在正在使用表达式语言来寻找表达式断言,但是我已经耗尽了想法,为此花了我几天的时间,因此在这一点上我需要您的帮助,以找出我做错了什么,被忽略或尚未这么做。
谢谢。
更新:添加了一个自定义验证器,在该验证器中,我不确定是否正确管理了空数据或任何相关内容。
// ValidPassword.php
namespace XXX\UsersBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
*/
class ValidPassword extends Constraint
{
public $message = 'InvalidPasswordMessage';
}
(我希望消息由翻译文件处理。)
// ValidPasswordValidator.php
namespace XXX\UsersBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use XXX\UsersBundle\Entity\User;
class ValidPasswordValidator extends ConstraintValidator
{
public function validate($p, Constraint $constraint)
{
$success = true;
if (strlen($p)) {
$success = (strlen($p)>7 && preg_match('/[A-Za-z]/', $p) && preg_match('/[0-9]/', $p));
}
if (!$success) {
$this->context->buildViolation($constraint->message)
->addViolation();
}
}
在实体中:
use XXX\UsersBundle\Validator\Constraints as UserAssert;
...
/**
* @var string
* @UserAssert\ValidPassword
*/
private $plainPassword;
这是树枝模板的一部分,用于显示涉及的字段:
...
<div class="row">
<div class="col-md-4">
{{ form_row(form.name) }}
</div>
<div class="col-md-4">
{{ form_row(form.surname) }}
</div>
</div>
<div class="row">
<div class="col-md-4">
{{ form_row(form.email) }}
</div>
</div>
<div class="row">
<div class="col-md-4">
{{ form_row(form.plainPassword) }}
</div>
</div>
答案 0 :(得分:0)
您的代码几乎完成了。您的麻烦是您正在使用
'error_bubbling' => true
此配置将错误对象更改为附加到父字段目标或表单的对象。因此,在您的情况下,plainPasswordField中的错误将添加到表单而不是字段中。
进行了一些测试之后,我想关于Form Errors会有些混乱 和表单字段错误。
如果您的视图代码没有 form_errors(form)或 form(form),则所有 form.vars.errors 都不会显示出来。
具有 error_bubbling = true 或类似代码的子表单字段:
// Generic Controller
$form->addError(new FormError('My Generic Form Error not associate with any field!'));
return $this->render('my_template.html.twig', [
'form' => $form->createView(),
]);
olny可以显示在树枝模板中,
form_errors(form)
有用的提示:
在创建表单模板时,请使用form(form)
(必须是模板的第一个调用)调试表单视图,以显示表单对象中的所有内容,例如字段(使用html表单输入| select,
字段标签,字段错误,字段助手)和表单本身中的错误
该文档说了form_rest()
,但未显示form.vars.errors
使用form.vars.errors|length
检查树枝中表单视图变量上的错误