Yii2 唯一验证器被忽略
Yii2 unique validator ignored
在我的 RegisterForm 模型的 rules()
中:
[ 'user_username', 'unique', 'targetClass' => 'app\models\User', 'message' => 'This username is already been taken.' ],
在我的控制器中:
$model = new RegisterForm();
if ( $model->load( Yii::$app->request->post() ) ) {
if ( $user = $model->register() ) {
return $this->redirect( [ '/login' ] );
}
}
在注册表中:
public function register() {
$user = new User();
$user->user_firstname = $this->user_firstname;
$user->user_lastname = $this->user_lastname;
$user->user_username = $this->user_username;
$user->user_email = $this->user_email;
$user->setPassword( $this->user_password );
if ( !$user->validate() ) {
return null;
}
if ( $user->save() ) {
return $user;
}
return null;
}
表格:
<?php $form = ActiveForm::begin(); ?>
<?= $form->field( $model, 'user_firstname' )->textInput( [ 'maxlength' => true ] ) ?>
<?= $form->field( $model, 'user_lastname' )->textInput( [ 'maxlength' => true ] ) ?>
<?= $form->field( $model, 'user_username' )->textInput( [ 'maxlength' => true ] ) ?>
<?= $form->field( $model, 'user_email' )->textInput( [ 'maxlength' => true ] ) ?>
<?= $form->field( $model, 'user_password' )->passwordInput() ?>
<?= $form->field( $model, 'user_password_repeat' )->passwordInput() ?>
<?= Html::submitButton( 'Register', [ 'class' => 'btn btn-primary', 'name' => 'register-button' ] ) ?>
<?php ActiveForm::end(); ?>
然而,当我输入一个我知道已经存在的用户名时,错误永远不会出现,记录会尝试保存,但我得到:Integrity constraint violation: 1062 Duplicate entry ...
编辑:如果我将唯一规则添加到用户模型本身,如果我输入存在的用户名,表单将不会提交,错误就不会出现
正如我所怀疑的,您没有在客户端检查唯一的 user_username
属性。它不起作用的原因是因为您没有发送 Ajax 请求来检查数据库的结果。与其他规则不同,unique
规则需要向服务器发出额外的 Ajax 请求,因为如果 Javascript 会检索所有当前注册的用户名并将其存储在客户端的某个位置,那将是一件非常糟糕的事情。
为了解决你的问题,在表格中这样写:
$form = ActiveForm::begin([
'enableAjaxValidation' => true,
'validationUrl' => [<URL HERE>],
]);
现在你必须在控制器中创建一个方法(动作),returns 验证(不仅仅是唯一的,所有的)返回到 ActiveForm
。所以它可能是这样的:
public function actionAjaxValidation()
{
$post = Yii::$app->request->post();
$model = new YourClass();
if (!$model->load($post)) {
throw new HttpException(403, 'Cannot load model');
}
$array = ActiveForm::validate($model);
return json_encode($array);
}
在我的 RegisterForm 模型的 rules()
中:
[ 'user_username', 'unique', 'targetClass' => 'app\models\User', 'message' => 'This username is already been taken.' ],
在我的控制器中:
$model = new RegisterForm();
if ( $model->load( Yii::$app->request->post() ) ) {
if ( $user = $model->register() ) {
return $this->redirect( [ '/login' ] );
}
}
在注册表中:
public function register() {
$user = new User();
$user->user_firstname = $this->user_firstname;
$user->user_lastname = $this->user_lastname;
$user->user_username = $this->user_username;
$user->user_email = $this->user_email;
$user->setPassword( $this->user_password );
if ( !$user->validate() ) {
return null;
}
if ( $user->save() ) {
return $user;
}
return null;
}
表格:
<?php $form = ActiveForm::begin(); ?>
<?= $form->field( $model, 'user_firstname' )->textInput( [ 'maxlength' => true ] ) ?>
<?= $form->field( $model, 'user_lastname' )->textInput( [ 'maxlength' => true ] ) ?>
<?= $form->field( $model, 'user_username' )->textInput( [ 'maxlength' => true ] ) ?>
<?= $form->field( $model, 'user_email' )->textInput( [ 'maxlength' => true ] ) ?>
<?= $form->field( $model, 'user_password' )->passwordInput() ?>
<?= $form->field( $model, 'user_password_repeat' )->passwordInput() ?>
<?= Html::submitButton( 'Register', [ 'class' => 'btn btn-primary', 'name' => 'register-button' ] ) ?>
<?php ActiveForm::end(); ?>
然而,当我输入一个我知道已经存在的用户名时,错误永远不会出现,记录会尝试保存,但我得到:Integrity constraint violation: 1062 Duplicate entry ...
编辑:如果我将唯一规则添加到用户模型本身,如果我输入存在的用户名,表单将不会提交,错误就不会出现
正如我所怀疑的,您没有在客户端检查唯一的 user_username
属性。它不起作用的原因是因为您没有发送 Ajax 请求来检查数据库的结果。与其他规则不同,unique
规则需要向服务器发出额外的 Ajax 请求,因为如果 Javascript 会检索所有当前注册的用户名并将其存储在客户端的某个位置,那将是一件非常糟糕的事情。
为了解决你的问题,在表格中这样写:
$form = ActiveForm::begin([
'enableAjaxValidation' => true,
'validationUrl' => [<URL HERE>],
]);
现在你必须在控制器中创建一个方法(动作),returns 验证(不仅仅是唯一的,所有的)返回到 ActiveForm
。所以它可能是这样的:
public function actionAjaxValidation()
{
$post = Yii::$app->request->post();
$model = new YourClass();
if (!$model->load($post)) {
throw new HttpException(403, 'Cannot load model');
}
$array = ActiveForm::validate($model);
return json_encode($array);
}