Yii2 根据条件添加规则
Yii2 add rule based on condition
我正在使用 PHP Yii2 框架和 dektrium\yii2-user 用户身份验证扩展构建网站。
如果登录失败次数超过 3 次,我想向用户询问验证码,但默认情况下扩展不支持此功能。
现在,我已经覆盖了扩展程序的用户和登录表单模型,并添加了所需的字段和检查。但是,我不知道如何添加一条规则,使验证码仅在第四次尝试时才需要。
是否可以动态添加规则?我在下面显示了一个简化的代码视图以及我需要帮助的评论。我会写函数,只需要注释部分的帮助。
<?php
namespace app\models\dektrium\user;
class LoginForm extends \dektrium\user\models\LoginForm
{
public $captcha;
public $need_captcha;
public function rules() {
$rules = parent::rules();
//This is how you'd normally add a rule, but this will require it for every login
//The following rule should be added from the login()
$rules[] = ['captcha', 'captcha', 'message' => 'Too many attempts. Captcha required.'];
$rules[] = ['need_captcha', 'boolean'];
return $rules;
}
public function login() {
$success = false;
$requireCaptcha = false;
if ($this->validate() && $this->user) {
if ($this->user->login_attempts > 3) {
//add rule here to require captcha
$requireCaptcha = true;
}
$success = !$requireCaptcha && $this->validateCaptcha() && $this->validateLogin();
if ($success) {
$this->user->updateAttributes(['last_login_at' => time()]);
}
}
return $success;
}
}
?>
编辑:
如果有一个'optional'参数与'required'相反,那就足够了。我可以在我的 login() 中检查验证码。
编辑 2:
我尝试使用如下场景,但在进行验证之前,模型没有在控制器操作中加载验证码值。
<?php
namespace app\models\dektrium\user;
class LoginForm extends \dektrium\user\models\LoginForm
{
public $captcha;
public $need_captcha;
public $login_count;
public function rules() {
$rules = parent::rules();
$rules[] = ['captcha', 'captcha', 'message' => 'Too many attempts. Captcha required.', 'on' => ['required_captcha']];
$rules[] = ['need_captcha', 'boolean'];
$rules[] = ['login_count', 'integer'];
return $rules;
}
public function login() {
$this->user = $this->finder->findUserByUsernameOrEmail(trim($this->login));
if($this->user && $this->user->login_count > 3) {
$this->scenario = 'required_captcha';
$this->need_captcha = true;
}
$success = parent::login();
if ($success) {
$this->user->login_count = 0;
$this->user->save();
} else {
$this->login_count++;
if ($this->user) {
$this->user->login_count++;
$this->user->save();
}
}
if ($this->login_count > 3) {
$this->scenario = 'required_captcha';
$this->need_captcha = true;
}
return $success;
}
}
这就是我最终这样做的方式...
我使用了基于场景的规则,在控制器操作中,我在需要验证码的条件为真时设置了场景。实际上,控制器也是任意扩展的,所以我不得不做一些支持的控制器映射,并通过事件设置场景。
我第一次尝试这样做失败了,因为我在验证功能期间设置了场景,但应该在这样做之前设置它,它起作用了。
<?php
namespace app\models\dektrium\user;
class LoginForm extends \dektrium\user\models\LoginForm
{
public $captcha;
public $need_captcha;
public $login_count;
public function rules() {
$rules = parent::rules();
$rules[] = ['captcha', 'required', 'on' => ['use_captcha']];
$rules[] = ['captcha', 'captcha', 'on' => ['use_captcha']];
$rules[] = ['need_captcha', 'boolean'];
$rules[] = ['login_count', 'integer'];
return $rules;
}
public function login() {
$success = true;
$this->user = $this->finder->findUserByUsernameOrEmail(trim($this->login));
if(!$this->need_captcha && $this->user && $this->user->login_count > 3) {
$this->need_captcha = true;
$success = false;
}
$success = $success && parent::login();
if ($success) {
$this->user->login_count = 0;
$this->user->save();
} else {
$this->login_count++;
if ($this->user) {
$this->user->login_count++;
$this->user->save();
}
if ($this->login_count > 2)
$this->need_captcha = true;
}
return $success;
}
}
使用
['field', 'required', 'when' => function($model) { return your_true_condition; }
设置验证规则时。
条件可以是 session/cookie 中的某个值,比如每次递增的整数
我正在使用 PHP Yii2 框架和 dektrium\yii2-user 用户身份验证扩展构建网站。
如果登录失败次数超过 3 次,我想向用户询问验证码,但默认情况下扩展不支持此功能。
现在,我已经覆盖了扩展程序的用户和登录表单模型,并添加了所需的字段和检查。但是,我不知道如何添加一条规则,使验证码仅在第四次尝试时才需要。
是否可以动态添加规则?我在下面显示了一个简化的代码视图以及我需要帮助的评论。我会写函数,只需要注释部分的帮助。
<?php
namespace app\models\dektrium\user;
class LoginForm extends \dektrium\user\models\LoginForm
{
public $captcha;
public $need_captcha;
public function rules() {
$rules = parent::rules();
//This is how you'd normally add a rule, but this will require it for every login
//The following rule should be added from the login()
$rules[] = ['captcha', 'captcha', 'message' => 'Too many attempts. Captcha required.'];
$rules[] = ['need_captcha', 'boolean'];
return $rules;
}
public function login() {
$success = false;
$requireCaptcha = false;
if ($this->validate() && $this->user) {
if ($this->user->login_attempts > 3) {
//add rule here to require captcha
$requireCaptcha = true;
}
$success = !$requireCaptcha && $this->validateCaptcha() && $this->validateLogin();
if ($success) {
$this->user->updateAttributes(['last_login_at' => time()]);
}
}
return $success;
}
}
?>
编辑:
如果有一个'optional'参数与'required'相反,那就足够了。我可以在我的 login() 中检查验证码。
编辑 2:
我尝试使用如下场景,但在进行验证之前,模型没有在控制器操作中加载验证码值。
<?php
namespace app\models\dektrium\user;
class LoginForm extends \dektrium\user\models\LoginForm
{
public $captcha;
public $need_captcha;
public $login_count;
public function rules() {
$rules = parent::rules();
$rules[] = ['captcha', 'captcha', 'message' => 'Too many attempts. Captcha required.', 'on' => ['required_captcha']];
$rules[] = ['need_captcha', 'boolean'];
$rules[] = ['login_count', 'integer'];
return $rules;
}
public function login() {
$this->user = $this->finder->findUserByUsernameOrEmail(trim($this->login));
if($this->user && $this->user->login_count > 3) {
$this->scenario = 'required_captcha';
$this->need_captcha = true;
}
$success = parent::login();
if ($success) {
$this->user->login_count = 0;
$this->user->save();
} else {
$this->login_count++;
if ($this->user) {
$this->user->login_count++;
$this->user->save();
}
}
if ($this->login_count > 3) {
$this->scenario = 'required_captcha';
$this->need_captcha = true;
}
return $success;
}
}
这就是我最终这样做的方式...
我使用了基于场景的规则,在控制器操作中,我在需要验证码的条件为真时设置了场景。实际上,控制器也是任意扩展的,所以我不得不做一些支持的控制器映射,并通过事件设置场景。
我第一次尝试这样做失败了,因为我在验证功能期间设置了场景,但应该在这样做之前设置它,它起作用了。
<?php
namespace app\models\dektrium\user;
class LoginForm extends \dektrium\user\models\LoginForm
{
public $captcha;
public $need_captcha;
public $login_count;
public function rules() {
$rules = parent::rules();
$rules[] = ['captcha', 'required', 'on' => ['use_captcha']];
$rules[] = ['captcha', 'captcha', 'on' => ['use_captcha']];
$rules[] = ['need_captcha', 'boolean'];
$rules[] = ['login_count', 'integer'];
return $rules;
}
public function login() {
$success = true;
$this->user = $this->finder->findUserByUsernameOrEmail(trim($this->login));
if(!$this->need_captcha && $this->user && $this->user->login_count > 3) {
$this->need_captcha = true;
$success = false;
}
$success = $success && parent::login();
if ($success) {
$this->user->login_count = 0;
$this->user->save();
} else {
$this->login_count++;
if ($this->user) {
$this->user->login_count++;
$this->user->save();
}
if ($this->login_count > 2)
$this->need_captcha = true;
}
return $success;
}
}
使用
['field', 'required', 'when' => function($model) { return your_true_condition; }
设置验证规则时。
条件可以是 session/cookie 中的某个值,比如每次递增的整数