Php Yii2根据条件添加规则

Php Yii2根据条件添加规则,php,dynamic,yii2,rules,Php,Dynamic,Yii2,Rules,我正在使用PHP Yii2框架和dektrium\Yii2用户扩展构建一个网站,用于用户身份验证 如果不成功登录的次数超过三次,我想向用户索要验证码,但默认情况下扩展不支持这一点 现在,我已经覆盖了扩展的用户和LoginForm模型,并添加了所需的字段和检查。然而,我不知道如何添加一个规则,使验证码只需要从第四次尝试 是否可以动态添加规则?我在下面展示了一个简化的代码视图和我需要帮助的注释。我将写的功能,只是需要帮助与评论部分 <?php namespace app\models\dek

我正在使用PHP Yii2框架和dektrium\Yii2用户扩展构建一个网站,用于用户身份验证

如果不成功登录的次数超过三次,我想向用户索要验证码,但默认情况下扩展不支持这一点

现在,我已经覆盖了扩展的用户和LoginForm模型,并添加了所需的字段和检查。然而,我不知道如何添加一个规则,使验证码只需要从第四次尝试

是否可以动态添加规则?我在下面展示了一个简化的代码视图和我需要帮助的注释。我将写的功能,只是需要帮助与评论部分

<?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;
    }
}

?>

以下是我最终如何做到这一点的

我使用了一个基于场景的规则,在控制器操作中,当我需要验证码的条件为真时,我设置了场景。实际上,控制器也是任意扩展的,因此我必须进行一些受支持的控制器映射,并通过事件设置场景

我第一次尝试这样做失败了,因为我在验证函数期间设置了场景,但可能应该在这样做之前设置它,因为它在哪里工作

<?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'=>函数($model){返回您的_true_条件;}
设置验证规则时


条件可以是session/cookie中的某个内容,比如每次递增的整数

您可以共享操作的代码吗?您的规则是可疑的。如果您使用的是
load()
在某个地方,用户可以将值传递给
需要验证码
登录计数
属性,并完全绕过验证码。@rob006这就是$this->user->login\u count的原因。所有失败的尝试都会记录到数据库中,并且login()从第三次尝试开始总是希望获得验证码。
<?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;
    }
}