2012-11-23 29 views

回答

5

在模型中必須做這樣的事情:

public function rules() { 
    return array(
     array('name, username, email, password', 'required', 'on' => 'create'), 
     array('name, username, email', 'required', 'on' => 'update'), 
    ); 
} 

讓我們說,你現在運行方案是更新。所以我不需要那裏的密碼。我只在創建場景中需要它。所以,你有你刪除密碼字段,你有行動,你裏面包含這個視圖文件:

$model->setScenario('update'); 

這樣就不需要密碼,它會保持不變。

對於密碼更改,您可以創建一個新的操作(例如actionPassChange),您需要輸入兩次新密碼。

+0

兄弟感謝您的幫助,但是這一個不起作用 –

+0

如果您按照方案選項,那麼對於您現在運行的操作,您必須在加載$模型後立即設置方案。通過從視圖中刪除密碼字段,驗證將不需要此屬性。請指定您的錯誤以更好地瞭解您的問題。 –

+0

你可以解釋我breifly? –

2
$model->attributes=$_POST['JbJsJobResume']; 

,而不是分配所有屬性只分配這些只有你想保存,作爲

$model->name=$_POST['JbJsJobResume']['name']; 
$model->save(); 
+0

$ model-> name = $ _ POST ['JbJsJobResume' ]['名稱'];是否['name']是db字段名稱或表單字段名稱? –

+0

$ model-> name here是表列名稱和$ _POST ['JbJsJobResume'] ['name'];是表單數據。 print_r($ _ POST)並查找數據在哪個後期變量中。 – Hemc

7

我認爲更好的辦法是在這種情況下不使用的情況。規則中的下一個代碼僅對該場景說:需要下一個字段。但不是:跳過其他人

array('name, username, email', 'required', 'on' => 'update'), 

例如,如果我們限制密碼的長度超過32個字符,但在一個數據庫被存儲在一個格式SHA1(長度40),那麼我們有一個問題,因爲該驗證器將阻止數據庫query.This是因爲當你進行更新時,「validatе」方法檢查所有類屬性(關於數據庫表映射),而不僅僅是通過post發佈的新屬性。

可以使用「saveAttributes」方法,但後來我注意到另一個問題。如果數據庫中的「email」列是唯一的,並且編輯後的電子郵件與現有的電子郵件重複,那麼規則中定義的Yii消息系統無法通知和拋出錯誤代碼作爲數據庫查詢。

我認爲最簡單的方法是:在這種情況下不要設置場景。只需發送你想要的屬性作爲參數。這將保留由GII創建的所有CRUD功能。

在你的代碼,它看起來像這樣: (模型)

public function rules() { 
    return array(
     array('name, username, email, password', 'required'), 
    ); 
} 

(在控制器)

if($id==Yii::app()->user->id){ 
    $model=$this->loadModel($id); 
    if(isset($_POST['JbJsJobResume'])) { 
     $model->attributes=$_POST['JbJsJobResume']; 
     if($model->save(true, array('name', 'username', 'email'))) 
      $this->redirect(array('view','id'=>$model->id)); 
    } 

    $this->render('update',array('model'=>$model,)); 
} 

我注意到,您不使用RBAC。它非常方便和靈活 - 試一試。

http://www.yiiframework.com/doc/guide/1.1/en/topics.auth#role-based-access-control

+0

只需要指出saveAttributes()不會對要保存的數據進行驗證。 – crafter

+0

爲我工作就像魅力+1 :) – Pupil

1

1日選項正好被清除密碼字段設置前:

function update(){ 
    $model=$this->loadModel($id); 
    unset($_POST['JbJsJobResume']['password']); 
    $model->attributes=$_POST['JbJsJobResume']; 
    $model->save(); 
} 

第二個選項:使用臨時變量:

function update(){ 
    $model=$this->loadModel($id); 
    $temPassword = $model->passwrod; 
    $model->attributes=$_POST['JbJsJobResume']; 
    $model->passwrod = $temPassword; 
    $model->save(); 
} 

第三選項:使用scenarios

1

我我不知道爲什麼這是一個問題,還有一些鱈魚e可以幫助我們理解爲什麼。如果您不希望捕獲/更新密碼,那麼爲什麼表單中的密碼字段?

如果您從視圖中刪除密碼字段,密碼字段的值將不會被回發給控制器,然後它不會被更新。

有一種可能性是,上述方法不起作用,這可能是在您的用戶模式中,用戶在afterValidate方法?:

protected function afterValidate() 
{ 
    parent::afterValidate(); 
    $this->password = $this->encrypt($this->password); 
} 

public function encrypt($value) 
{ 
    return md5($value); 
} 

在這種情況下加密的密碼,如果你刪除視圖中的密碼字段,只需更新名稱,用戶名或電子郵件,然後密碼的md5哈希將自動重新哈希,您將失去真實密碼。

解決此問題的一種方法是在afterValidate方法(創建或更新)中密碼md5,但是如果用戶希望更改配置文件詳細信息(以相同的形式),請求用戶再次驗證其密碼。

  1. 形式:用戶更改名稱及驗證密碼
  2. 形式發佈
  3. 控制器調用身份驗證方法。
  4. 如果驗證屬實,覆蓋在用戶表中的條目(包括驗證PW)
-1

我覺得@肉汁的答案是正確的,感謝肉汁和尼科斯Tsirakis。我修復了與@faizphp幾乎相同的問題。我爲Nikos Tsirakis所說的用戶模型添加了一個場景,但也得到了同樣的問題。然後我發現我在User.afterValidate中加密了密碼,所以每次更新用戶模型時,程序再次將數據庫中的密碼加密爲錯誤的密碼。所以我改變了我的功能從

protected function afterValidate() 
{ 
     parent::afterValidate(); 
     if (!$this->hasErrors()) 
      $this->password = $this->hashPassword($this->password); 
} 
</code> 



protected function afterValidate() 
{ 
     parent::afterValidate(); 
     if (!$this->hasErrors() && $this->scenario==="create") 
      $this->password = $this->hashPassword($this->password); 
} 

。 它似乎工作。

相關問題