dozabt4329 2013-08-19 23:43
浏览 42
已采纳

使用CakePHP触发模型验证

I'm creating a form so users can change their passwords. This form is in my settings controller, but I'm saving the data to my users table.

I have the following form

settings/index.ctp

echo $this->Form->create('settings');
echo $this->Form->input('current_password');
echo $this->Form->input('password');
echo $this->Form->input('repass', array('type'=>'password', 'label'=>'Re-Enter Password'));
echo $this->Form->end(__('Submit'));

Here's my Setting model

function equalToField($array, $field) {
    print_r($array); //check to see if it was even being triggered...it's not!
    return strcmp($this->data[$this->alias][key($array)], $this->data[$this->alias][$field]) == 0;
}

public function beforeSave() {

    if (isset($this->data[$this->alias]['password'])) {
        $this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
    }
    return true;
}


 public $validate = array(
    'password' => array(
        'required' => array(
            'rule' => array('minLength', '8'),
            'message' => 'A password with a minimum length of 8 characters is required'
        )
    ),
    'repass' => array(
        'required' => array(
            'rule' => array('equalToField', 'password'),
            'message' => 'Passwords do not match'
        )
    )
);

And the code in my SettingsController to save it

$password = Security::hash($this->request->data['settings']['current_password'], NULL, true);
$this->loadmodel('User');
$options = array('conditions' => array('User.' . $this->User->primaryKey => AuthComponent::user('id')));
$user = $this->User->find('first', $options);

if($user['User']['password'] == $password){ //current password match 
    $this->User->id = AuthComponent::user('id');
    $this->User->saveField('password',Security::hash($this->request->data['settings']['password'], NULL, true));
}
else{
    $this->Session->setFlash('Current password is incorrect'); 
}

What am I doing incorrectly that the validation isn't triggering? I'd prefer to keep this in my SettingsController if possible. Also, before anyone mentions it I plan on making the current password match into one of the validation criteria...just as soon as I get it working.

Update - I decided to do some digging around

In /lib/Model/Model.php I went to the validator function and printed the validator object, here's what I found

([validate] => Array ( 
        [password] => Array ( 
             [required] => Array ( 
                  [rule] => Array ( 
                       [0] => minLength 
                       [1] => 8 ) 
                       [message] => A password with a minimum length of 8 characters is required ) ) 
        [repass] => Array ( 
             [required] => Array ( 
                   [rule] => Array ( 
                        [0] => equalToField 
                        [1] => password )
                        [message] => Passwords do not match 
   ) ) ) 
 [useTable] => settings 
 [id] => 
 [data] => Array ( 
                [Setting] => Array ( 
                          [settings] => Array ( 
                                [current_password] => current_pass 
                                [password] => testpass1 
                                [repass] => testpass2 
   ) ) )

I'm not sure if that's what I want, but it's using settings table for this and I'm saving to the users table. I changed that value to users (by manually setting the value in that function), but it didn't change anything.

When I use the following as was suggested, it pulls the validation from the UserModel not Settings

$this->User->set($this->request->data);
if($this->User->Validates() == true){
  • 写回答

1条回答 默认 最新

  • duanfu4446 2013-08-20 18:50
    关注

    Ok, let's start with a fresh, new answer. There are various problems here.

    1. Mixing up models

    You are defining the validation rules and stuff on the Setting model, but in your code snippet you are using the User model for saving the data, so if at all, it would apply the validation rules defined on the User model. So while it's possible to use a different model for validation than for saving, I wouldn't recommend that, I would instead use the User model for all these jobs.

    That means, put the validation rules and methods in your User model (that is hopefully linked to the users table).


    2. Lowercase/plural notation for model names

    You are using lowercase/plural notation for model names, where it should be singular starting with a capital letter:

    $this->Form->create('Setting');
    
    $this->request->data['Setting']
    

    Please note that this is just for demonstration purposes, as mentioned above you should use the User model, ie:

    $this->Form->create('User');
    
    $this->request->data['User']
    

    3. Validation is applied to explicitly passed data only

    Model::saveField() only validates the data that was explicitly passed to it, ie it would only validate the password field, and you couldn't access any other fields from your validation methods since the data is not set on the model.

    So instead you'll either have to use Model::save() with a list of allowed fields supplied (you could also utilize Model::set()):

    $this->User->id = AuthComponent::user('id');
    $this->User->save($this->request->data, true, array('password', 'repass'));
    

    or you do trigger validation manually:

    $this->User->id = AuthComponent::user('id');
    $this->User->set($this->request->data);
    if($this->User->validates() === true)
    {
        $this->User->saveField('password', Security::hash($this->request->data['User']['password'], NULL, true));
    }
    

    Note that in this scenario you could also use a different model for validation, ie:

    $this->Setting->set($this->request->data);
    if($this->Setting->validates() === true)
    {
        $this->User->saveField('password', Security::hash($this->request->data['User']['password'], NULL, true));
    }
    

    However, I think it's better to use the User model, if necessary change validation rules dynamically so that they fit your needs. For example by removing rules:

    $this->User->validator()->remove('field_x')
                            ->remove('field_y')
                            ->remove('field_z');
    

    Or by overriding the validation rules:

    $this->User->validate = array
    (
        ...
    );
    

    However, both is best to be done from within the model.


    4. Triggering validation with Model::saveField()

    Last but not least, the Model::saveField() method has 3 parameters, where the third one is a either a boolean value (defaults to false), defining whether or not to use validation, or an array that takes the options validate, callbacks and counterCache.

    So you would have to set true as the third parameter in order for validation being triggered by Model::saveField() at all:

    $this->User->saveField('password', Security::hash($this->request->data['User']['password'], NULL, true), true);
    

    ps. are you aware that you are currently hashing twice? First directly when passing the data to Model::saveField(), and then a second time in Model::beforeSave().

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码