2013-08-19 125 views
2

我正在創建一個表單,以便用戶可以更改其密碼。此表單位於我的設置控制器中,但我將數據保存到我的用戶表中。使用CakePHP觸發模型驗證

我有以下形式

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){ 
+0

這也可能有所幫助:http://www.dereuromark.de/2011/08/25/working-with-passwords-in-cakephp/ – mark

+0

不知道爲什麼我沒有發現,現在我'米糊塗,你在那裏做什麼?你爲什麼使用'User'模型來保存屬於'Setting'模型的東西? – ndm

+0

@ndm它被保存在users表中,而不是設置表中。我正在從SettingsController /模型 – user1443519

回答

4

好的驗證,讓我們開始一個新的,新的答案。這裏有各種各樣的問題。

1.混合後續機型

你定義在Setting模型驗證規則之類的東西,但在您的代碼段,你正在使用的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)); 
} 

但是,我認爲使用用戶模型會更好,如有必要,請動態更改驗證規則,以便它們適合您的需求。例如通過移除規則:

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

或者通過覆蓋驗證規則:

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

但是,這兩個最好從模型內完成。


4. Model::saveField()

最後但觸發驗證並非最不重要的,該Model::saveField()方法具有3個參數,其中,第三個是一個或者是boolean值(默認爲false),定義是否要使用驗證,或採取選項validate,callbackscounterCachearray

所以,你將不得不設置true作爲第三個參數,以便確認被Model::saveField()在所有觸發:

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

PS。你知道你現在正在哈希兩次嗎?首先直接將數據傳遞到Model::saveField(),然後在Model::beforeSave()中第二次。

+0

哇!你真的全力以赴。非常感謝! – user1443519

+1

不客氣... – ndm