【问题标题】:Triggering model validation with CakePHP使用 CakePHP 触发模型验证
【发布时间】:2013-08-19 23:43:38
【问题描述】:

我正在创建一个表单,以便用户可以更改他们的密码。此表单在我的设置控制器中,但我将数据保存到我的用户表中。

我有以下表格

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'));

这是我的设置模型

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'
        )
    )
);

以及我的 SettingsController 中的代码来保存它

$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'); 
}

验证未触发,我做错了什么?如果可能的话,我宁愿把它保存在我的 SettingsController 中。此外,在任何人提到它之前,我计划将当前密码匹配为验证标准之一......只要我让它工作。

更新 - 我决定做一些挖掘工作

在 /lib/Model/Model.php 中,我转到验证器函数并打印了验证器对象,这是我找到的

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

我不确定这是否是我想要的,但它为此使用了设置表,我正在保存到用户表中。我将该值更改为用户(通过手动设置该函数中的值),但它没有改变任何东西。

当我按照建议使用以下内容时,它会从 UserModel 而不是设置中提取验证

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

【问题讨论】:

  • 不知道为什么我没有发现...现在我很困惑,你在那里做什么?为什么要使用User 模型来保存属于Setting 模型的东西?
  • @ndm 它被保存在用户表中,而不是设置表中。我正在从 SettingsController/model 执行此操作
  • 好的,但是您希望它如何工作?您正在对 Setting 模型定义验证(至少当您说“这是我的设置模型”时我假设是这样),但是您使用的是 User 模型,这就是不对我来说没有意义,我不确定这是否是我应该在回答中详细说明的错误,或者您是否正在做一些时髦的事情,例如扩展 Setting 模型或其他东西。
  • @ndm 那么如何将它保存到用户表中呢?我唯一的选择是把它放在 UsersController 中吗?我只能将我正在验证的模型保存到表中吗?

标签: php validation cakephp model


【解决方案1】:

好的,让我们从一个全新的答案开始。这里有各种各样的问题。

1。混合模型

您在 Setting 模型上定义验证规则和内容,但在您的代码 sn-p 中,您使用 User 模型来保存数据,所以如果有的话,它将应用定义的验证规则在User 模型上。因此,虽然可以使用与保存不同的模型进行验证,但我不建议这样做,我会为所有这些工作使用 User 模型。

这意味着,将验证规则和方法放入您的 User 模型(希望链接到 users 表)。


2。型号名称的小写/复数表示法

您正在对模型名称使用小写/复数表示法,其中它应该以大写字母开头的单数:

$this->Form->create('Setting');

$this->request->data['Setting']

请注意,这仅用于演示目的,如上所述,您应该使用User 模型,即:

$this->Form->create('User');

$this->request->data['User']

3。验证仅适用于显式传递的数据

Model::saveField() 仅验证显式传递给它的数据,即它只会验证 password 字段,并且您无法通过验证方法访问任何其他字段,因为数据未在模型上设置.

因此,您要么必须使用 Model::save() 并提供允许的字段列表(您也可以使用 Model::set()):

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

或者你做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));
}

请注意,在这种情况下,您还可以使用不同的模型进行验证,即:

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

但是,我认为最好使用 User 模型,如有必要,动态更改验证规则以使其符合您的需求。例如通过删除规则:

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

或者通过覆盖验证规则:

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

但是,两者都最好在模型内完成。


4。使用Model::saveField() 触发验证

最后但同样重要的是,Model::saveField() 方法有 3 个参数,其中第三个参数是 boolean 值(默认为 false),定义是否使用验证,或 array采用validatecallbackscounterCache 选项。

因此,您必须将true 设置为第三个参数才能完全由Model::saveField() 触发验证:

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

ps。你知道你目前正在哈希两次吗?第一次直接将数据传递给Model::saveField(),然后第二次传入Model::beforeSave()

【讨论】:

  • 哇!你真的全力以赴。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2012-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多