Yii 在不实例化模型的情况下,如何使用CActiveRecord方法将db字段更新为自身的函数?

Yii 在不实例化模型的情况下,如何使用CActiveRecord方法将db字段更新为自身的函数?,yii,query-builder,Yii,Query Builder,假设我从带有id和库存字段的表中有一个型号产品。我只需要将in_stock值更新为(in_stock+added_stock)。有没有一种方法可以在不创建模型实例的情况下使用Yii函数对其进行更新?我试过了 Product::model()->updateByPk($id,array('in_stock'=>'in_stock+'.$added_stock)); 但它不起作用。 欢迎使用任何解决方案。我猜您打算将$added\u stock作为本地PHP变量?如果是这样,这可能是最

假设我从带有
id
库存
字段的表中有一个型号
产品
。我只需要将
in_stock
值更新为
(in_stock+added_stock)
。有没有一种方法可以在不创建模型实例的情况下使用Yii函数对其进行更新?我试过了

Product::model()->updateByPk($id,array('in_stock'=>'in_stock+'.$added_stock));
但它不起作用。
欢迎使用任何解决方案。

我猜您打算将
$added\u stock
作为本地PHP变量?如果是这样,这可能是最好的方法:

Product::model()->updateCounters(
    array('in_stock' => $added_stock), 
    array('condition'=>'id = :id'),
    array(':id' => $id)

);
这样可以在不查询记录的情况下向字段添加任意数量的数据。 它还将把
$added_stock
变量转换成一个整数,这样就不用担心SQL注入或需要将其放入参数中


p.S也适用于小数。虽然我不想知道为什么你要处理股票单位的分数??)

虽然我不太清楚为什么要避免创建模型实例,但您可以这样做:

$sql = "SELECT in_stock FROM Product t WHERE id=:id";
$params = array(':id'=>$id);
$in_stock = Yii::app()->db->createCommand($sql)->queryScalar($params);

Product::model()->updateByPk($id, array(
  'is_stock'=>$added_stock+$in_stock,
);
当然,这样做似乎要做更多的工作。您总是可以在产品模型中用自己的静态方法包装它,并以这种方式调用它

public static function addStock($id,$added_stock){
  (place code from above here)
}

你能详细说明一下为什么不想创建模型实例吗?

正如其他人提到的,我不确定你为什么不能在这里创建一个模型实例并以这种方式进行,但当你问这个问题时,我想你有一个原因

在这种情况下,如果您无法创建模型,并且希望静态地创建模型,那么可以使用创建表达式,这样查询生成器就不会转义整个表达式(在您的示例中就是这样)

像这样的事情会奏效

$added_stock = 1;
$newStock = new CDbExpression('(`in_stock`+:addedStock)',array(
    ':addedStock' => $added_stock)
);
Product::model()->updateByPk($id,array(
    'in_stock' => $newStock
));

上述代码将按
$added\u stock
的值递增

谢谢你的回答。我想我的问题可能是因为库存中的
是一个十进制字段。执行上述查询,但每次都将值重置为0.0000。想法?不确定这是否能按您的意愿工作,即使使用正确的语法。params数组必须作为方法的第四个参数传递,第二个参数应该是
'column\u name'=>$new\u value
的关联数组。但是,根据其他类似方法的行为,$new_值将被转义并按原样应用于列。很可能它试图将您的命令作为字符串插入到十进制字段中。您是对的,这是完全错误的。我已经更新了一个有效的答案。这一次我刚试过。@Paystey有效!但是,我不得不将第二个属性改为字符串
'id=:id'
,而不是使用数组。更妙的是,它还能起到减量的作用。很好,很高兴它成功了。奇怪的是
条件
不过,在我发布之前,我完全使用了该代码进行测试。可能是Yii版本的不同,我想,我处于最前沿。不过没什么好担心的,它应该总是向后兼容的。我已经想到了这一点,但我想避免使用第一个
SELECT
。我在不同的表中有记录,当保存某个模型时,这些记录将被更新。只有第一条记录需要验证。我正在寻找的方法是下面的
updateCounters()
。然而,对于非计数器字段,您的答案非常出色。谢谢你已经+1'd了。为什么我不知道
CDbExpression
?我本可以让自己免于无数的头痛。哦,好吧,活到老学到老……没问题@Paystey&@topher。。。我以前没有听说过更新计数器,所以我们都学到了一些新东西!!:)CDbExpression非常适合将
NOW()
之类的值插入表中(还有许多其他功能!)