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().

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

报告相同问题?

悬赏问题

  • ¥20 给自己本科IT专业毕业的妹m找个实习工作
  • ¥15 用友U8:向一个无法连接的网络尝试了一个套接字操作,如何解决?
  • ¥30 我的代码按理说完成了模型的搭建、训练、验证测试等工作(标签-网络|关键词-变化检测)
  • ¥50 mac mini外接显示器 画质字体模糊
  • ¥15 TLS1.2协议通信解密
  • ¥40 图书信息管理系统程序编写
  • ¥20 Qcustomplot缩小曲线形状问题
  • ¥15 企业资源规划ERP沙盘模拟
  • ¥15 树莓派控制机械臂传输命令报错,显示摄像头不存在
  • ¥15 前端echarts坐标轴问题