Yii2,自定义验证:clientValidateAttribute() 无法正常工作

Posted

技术标签:

【中文标题】Yii2,自定义验证:clientValidateAttribute() 无法正常工作【英文标题】:Yii2, custom validation: clientValidateAttribute() doesn't work correctly 【发布时间】:2015-09-11 21:51:16 【问题描述】:

我有表单,由 ActiveForm 小部件创建。用户在那里输入波兰邮政编码。在适当的控制器中,我将输入的数据放入数据库中,例如:

$company_profile_data->postal_code = $_POST['CompanyProfiles']['postal_code'];
$company_profile_data->update();

我决定使用独立验证器进行邮政编码验证。 模型中该属性的规则

public function rules() 
    return [
        //...some other rules...
        ['postal_code', 'string', 'length' => [6,6]],
        ['postal_code', PostalValidator::className()], //standalone validator
    ];

app/components/validators/PostalValidator 类代码

namespace app\components\validators;

use yii\validators\Validator;
use app\models\CompanyProfiles;
use app\models\Users;

class PostalValidator extends Validator 
    public function init() 
        parent::init();
    

    public function validateAttribute($model, $attribute) 

    if (!preg_match('/^[0-9]2-[0-9]3$/', $model->$attribute))
        $model->addError($attribute, 'Wrong postal code format.');
    

public function clientValidateAttribute($model, $attribute, $view)  //want js-validation too
    $message = 'Invalid status input.';
    return <<<JS
if (!/^[0-9]2-[0-9]3$/.test("$model->$attribute")) 
    messages.push("$message");

JS;
    

因此,正确代码的示例是 00-202

当我(以用户角色)输入不正确的值时,页面重新加载并且我看到Wrong postal code format. 消息,尽管我重新定义了clientValidateAttribute 方法并编写了JS-validation,正如我所建议的那样,它不允许页面重新加载。然后我再次按下提交按钮:这次页面没有重新加载,我看到 Invalid status input. 消息(所以,第二次按下时间 JS 触发)。但是我之后输入正确的代码时,我仍然看到Invalid status input. 消息并且没有任何反应。

那么,我的clientValidateAttribute() 方法有什么问题? validateAttribute() 效果很好。

更新 来自控制器的片段

public function actionProfile() //can't use massive assignment here, cause info from 2 (not 1) user models is needed
    if (\Yii::$app->user->isGuest) 
        return $this->redirect('/site/index/');
    
    $is_user_admin = Users::findOne(['is_admin' => 1]);
    if ($is_user_admin->id == \Yii::$app->user->id)
        return $this->redirect('/admin/login/');

    $is_user_blocked = Users::find()->where(['is_blocked' => 1, 'id' => \Yii::$app->user->id])->one();
    if($is_user_blocked)
        return $this->actionLogout();

//3 model instances to retrieve data from users && company_profiles && logo
    $user_data = Users::find()->where(['id'=>\Yii::$app->user->id])->one();
    $user_data->scenario = 'update';

    $company_profile_data = CompanyProfiles::find()->where(['user_id'=>Yii::$app->user->id])->one();
    $logo = LogoData::findOne(['user_id' => \Yii::$app->user->id]);
    $logo_name = $logo->logo_name; //will be NULL, if user have never uploaded logo. In this case placeholder will be used

    $upload_logo = new UploadLogo();
    if (Yii::$app->request->isPost) 

        $upload_logo->imageFile = UploadedFile::getInstance($upload_logo, 'imageFile');

        if ($upload_logo->imageFile)  //1st part ($logo_data->imageFile) - whether user have uploaded logo
            $logo_file_name = md5($user_data->id);
            $is_uploaded = $upload_logo->upload($logo_file_name);
            if ($is_uploaded)  //this cond is needed, cause validation for image fails (?)
                //create record in 'logo_data' tbl, deleting previous
                if ($logo_name) 
                    $logo->delete();
                 else  //if upload logo first time, set val to $logo_name. Otherwise NULL val will pass to 'profile' view, and user wont see his new logo at once
                    $logo_name = $logo_file_name.'.'.$upload_logo->imageFile->extension;
                
                $logo_data = new LogoData;
                $logo_data->user_id = \Yii::$app->user->id;
                $logo_data->logo_name = $logo_name;
                $logo_data->save();
            
        
    

    if (isset($_POST['CompanyProfiles']))

        $company_profile_data->firm_data = $_POST['CompanyProfiles']['firm_data'];
        $company_profile_data->company_name = $_POST['CompanyProfiles']['company_name'];
        $company_profile_data->regon = $_POST['CompanyProfiles']['regon'];
        $company_profile_data->pesel = $_POST['CompanyProfiles']['pesel'];
        $company_profile_data->postal_code = $_POST['CompanyProfiles']['postal_code'];
        $company_profile_data->nip = $_POST['CompanyProfiles']['nip'];
        $company_profile_data->country = $_POST['CompanyProfiles']['country'];
        $company_profile_data->city = $_POST['CompanyProfiles']['city'];
        $company_profile_data->address = $_POST['CompanyProfiles']['address'];
        $company_profile_data->telephone_num = $_POST['CompanyProfiles']['telephone_num'];
        $company_profile_data->email = $_POST['CompanyProfiles']['email'];          
        $company_profile_data->update();
    

    if (isset($_POST['personal-data-button'])) 
        $user_data->username = $_POST['Users']['username'];
        $user_data->password_repeat = $user_data->password = md5($_POST['Users']['password']);
        $user_data->update();
    
    return $this->render('profile', ['user_data' => $user_data, 'company_profile_data' => $company_profile_data, 'upload_logo' => $upload_logo, 'logo_name' => $logo_name]);

【问题讨论】:

你正在使用加载功能?我想加载只在提交表单后调用。 不,我不使用它。我这样做(正如我上面写的):$company_profile_data-&gt;postal_code = $_POST['CompanyProfiles']['postal_code']。所以,我不使用大规模分配。您会看到,其他属性在没有任何load() 的情况下正确验证(在提交之前)。但不是在独立验证的情况下。 控制器有问题。您可以使用控制器代码更新帖子吗? 当然。以防万一我添加了 all actionProfile 代码,但是,我认为,最有趣的部分是在 IF stmt: if (isset($_POST['CompanyProfiles']))... 【参考方案1】:

我的错误在于clientValidateAttribute() 方法。而不是代码sn-p中的$model-&gt;$attribute

if (!/^[0-9]2-[0-9]3$/.test("$model->$attribute")) 

...我必须使用预定义的 JS-var value,因为这个 var 会随着输入值的变化而变化。所以,我的新代码是:

public function clientValidateAttribute($model, $attribute, $view) 
    return <<<JS
if (!/^[0-9]2-[0-9]3$/.test(value)) 
    messages.push("Wrong postal code format.");
 
JS;

【讨论】:

【参考方案2】:

模型直到not called any function 从模型中加载规则和行为。当你调用 $company_profile_data-&gt;update(); 模型调用 updatevalidate 函数。

尝试在$company_profile_data = CompanyProfiles::find()后添加此代码:

$company_profile_data->validate();

或者只使用load 函数。我认为这会有所帮助。

【讨论】:

两种情况都没有成功。但是,我想,我已经解决了这个问题。感谢您的参与。 :)

以上是关于Yii2,自定义验证:clientValidateAttribute() 无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

Yii2,自定义验证:clientValidateAttribute() 无法正常工作

Yii2.0自定义验证码

yii2中的rules自定义验证规则都有哪些

在自定义验证器中使用标准验证器进行 Grails 验证

Page_ClientValidate 正在验证多次。

yii2验证无效