Php 更新特定属性或字段

Php 更新特定属性或字段,php,yii,Php,Yii,问题1: 当我尝试save()任何Yii模型时,它会更新行中的所有字段。 问题是:当我尝试保存模型用户时,即使没有要更新的密码,它也会获取数据库值(已经散列)并再次散列。 我怎样才能只更新我想要的字段 代码: Users.php(模型): 问题2: 我有一个可以创建用户的API。 API教程: 当我在数据库中使用crypter_密码而不是password时,我得到一个错误:模型用户不允许使用参数密码,因为API使用$model->hasaAttribute()验证参数。 如何修复APIacti

问题1:

当我尝试
save()
任何Yii模型时,它会更新行中的所有字段。 问题是:当我尝试保存模型用户时,即使没有要更新的密码,它也会获取数据库值(已经散列)并再次散列。 我怎样才能只更新我想要的字段

代码:

Users.php(模型):


问题2:

我有一个可以创建用户的API。 API教程:

当我在数据库中使用crypter_密码而不是password时,我得到一个错误:
模型用户不允许使用参数密码
,因为API使用
$model->hasaAttribute()验证参数。
如何修复API
actionCreate
以允许自定义参数?

根据Yii的文档:

$attributes-数组-需要保存的属性列表。默认值为null,表示将保存从DB加载的所有属性

您可以传入要保存的字段数组。

save()
如果其
isNewRecord
属性为
true
,则在数据库表中插入一行。否则,它将更新表中相应的行(通常情况下,如果使用这些“查找”方法之一获取记录)

您需要做的是更新特定字段,这样您就可以使用它并接受已更新的字符串值数组。例如,演示代码如下

$user = Users::model()->findByAttributes(array('username'=>$this->username));
$user->ip = $_SERVER['REMOTE_ADDR'];
$user->SaveAttributes(array('ip'));

尽管这里列出的其他答案没有错,但它们肯定不是真正对开发人员友好的,而且很容易忘记将属性添加到保存行

这是一种开发人员友好的工作方式

在模型中,添加以下属性:

private $_aAttributesBackup;
在这个变量中,我们将存储当前模型的精确副本。为此,需要添加以下afterFind方法:

public function afterFind()
{
    $this->_aAttributesBackup = $this->attributes;
}
差不多了。此时,模型将把他的所有属性存储在attributesBackup字段中,这样比较起来就容易了。为了简化,我们还需要一个方法来检查指定的属性是否有备份值。为此,我们将以下代码添加到模型中:

public function getOriginalAttribute($sAttribute)
{
    if ($this->_aAttributesBackup)
    {
        return $this->_aAttributesBackup[$sAttribute];
    }

    return NULL;
}
现在,检查一下密码是否已更改?简单地说,在保存代码之前添加以下内容:

public function beforeSave()
{
    if ($this->getOriginalAttribute('password') != $this->password)
    {
        $this->password = sha1($this->password);
    }
    return parent::beforeSave();
}

瞧。现在,每次执行代码$Model->save();系统将检查密码是否已更改,如果密码已更改,它将再次对其进行哈希运算,如果密码未更改,则不会再次对其进行哈希运算。

我是否应使用系统的所有SAVE()以及要更改的正确参数?@luciannascimento要查看我的答案,请使用您可以测试的代码进行描述。我已阅读并测试,它工作得很好。只是想知道总是使用带有参数的SAVE()来创建一个安全的应用程序是否正确。@Luciannascimento不,通常你不必这样做。在我所有的UserController函数中,我都需要使用带参数的SAVE,否则密码散列会出问题。你有更好的办法来解决这个问题吗?SaveAttributes也验证模型?@AfnanBashir“还要注意,这个方法既不进行属性过滤也不进行验证。”对于这种情况,你不需要备份所有属性,只备份密码就够了。此外,在执行检查之前,您需要对密码执行相同的哈希。true:-),但为什么需要执行相同的哈希?在从数据库检索密码后,我们不会对其进行哈希解算,是吗?不,我们不会,但看起来密码是用户输入的。。因此,我们需要在比较之前再次对其进行哈希运算。您是否也需要检查空白密码字段?如果没有提供密码,但是在大量分配时发布了一个
$\u POST['Users']['password']
并将其添加到属性中,那么
如果($this->getOriginalAttribute('password')!=$this->password)
将返回true?谢谢您的输入,我没有想过!
public function afterFind()
{
    $this->_aAttributesBackup = $this->attributes;
}
public function getOriginalAttribute($sAttribute)
{
    if ($this->_aAttributesBackup)
    {
        return $this->_aAttributesBackup[$sAttribute];
    }

    return NULL;
}
public function beforeSave()
{
    if ($this->getOriginalAttribute('password') != $this->password)
    {
        $this->password = sha1($this->password);
    }
    return parent::beforeSave();
}