如何仅更新Yii框架中的某些字段?

时间:2012-11-23 10:42:06

标签: php yii

enter image description here

我不想更新密码fields.how使用this.Im使用md5编码为password.So我不想更新yii framework中的密码字段。任何帮助赞赏?

6 个答案:

答案 0 :(得分:7)

我认为更好的方法是在这种情况下不使用场景。规则中的下一个代码只是对场景说:需要下一个字段。但不是:跳过其他人

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

例如,如果我们将密码的长度限制为最多32个字符,但是在数据库中以sha1(长度为40)的格式存储,那么我们就会遇到问题,因为验证器将阻止数据库查询。这是因为当您进行更新时,“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

答案 1 :(得分: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),您需要输入两次新密码。

答案 2 :(得分:2)

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

而不是分配所有属性只分配那些你想要保存的属性, 如

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

答案 3 :(得分: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();  
}

第3个选项:使用scenarios

答案 4 :(得分:1)

我不确定为什么这是一个问题,一些代码可以帮助我们理解原因。如果您不想捕获/更新密码,那么为什么密码字段在表单中?

如果从视图中删除密码字段,密码字段的值将不会回发到控制器,然后不会更新。

上述方法可能不起作用,这可能是在您的用户模型中,您正在使用afterValidate方法加密密码?:

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

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

在这种情况下,如果从视图中删除密码字段,只更新名称,用户名或电子邮件,则密码的md5哈希值将自动重新散列,您将丢失真实密码。

解决此问题的一种方法是在afterValidate方法中创建密码md5(创建或更新),但是如果用户希望更改配置文件详细信息,请以相同的形式请求用户再次验证其密码。

  1. FORM:用户更改名称并验证密码
  2. 表格已发布
  3. 控制器调用身份验证方法。
  4. 如果验证为true,则覆盖用户表中的条目(包括已验证的pw)

答案 5 :(得分:-1)

我认为@ Gravy的答案是对的,谢谢Gravy和Nikos Tsirakis。我修复了与@faizphp几乎相同的问题。我为Nikos Tsirakis说的添加用户模型的场景,但也有同样的问题。然后我发现我在User.afterValidate中加密密码,所以每次更新User模型时,程序再次将数据库中的密码加密到错误的密码。所以我改变了我的功能

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

。 看起来很有效。