数据操作
本章节主要是介绍,通过模型对象实现新增记录、修改记录、删除记录等操作。查询记录的操作请查看上一节内容《数据查询》
一、保存数据
任何一个Web项目都会涉及到数据的增删改查操作,保存数据我们一般是通过save()方法来完成。save()方法既能实现新增,也能实现更新,您可以通过以下步骤轻松地将数据保存到数据库:

1. 准备一个 Active Record 实例

2. 将新值赋给 Active Record 的属性

3. 调用save()保存数据到数据库中。

例如:
// 插入新记录
$model = new \common\models\GoodsModel();
$model->goods_name = 'Apple iPhone 11';
$model->price = 4599.99;
$model->save(); // 或 $model->insert();

// 更新已经存在的数据
$model = \common\models\GoodsModel::find()->where(['goods_id' =>100])->one();
if($model) {
    $model->price = 5599.99;
    $model->save(); // 或 $model->update();
}
save()方法可能插入或者更新表的记录,这取决于Active Record实例的状态。 如果实例通过new操作符实例化,调用save()方法将插入新记录; 如果实例是一个查询方法的结果,调用save()方法 将更新这个实例对应的表记录行。注意:更新记录的情况下,查询结果不能加asArray()方法。
如果保存失败,会抛出异常,你可以通过$model->errors获取。以下是在控制器中的一个例子
namespace frontend\controllers\home;
use Yii;

use common\models\GoodsModel;
use common\library\Message;

use common\controllers\BaseMallController;

class GoodsController extends BaseMallController 
{
    public function actionIndex() 
    {
        // 新增记录
        $model = new GoodsModel();

        $post = [
            'goods_name' => 'Apple iPhone 11',
            'price'      => 4599.99
        ];
        foreach($post $key => $value) {
            $model->$key = $value;
        }
        if(!$model->save()) {
            // echo $model->errors;
            return Message::warning($model->errors);
        }

        // 新增成功后,我们还可以再进行修改操作
        $model->price = 5599.99;
        if(!$model->save()) { // 或者用 $model->update()
            return Message::warning($model->errors);
        }
        return Message::display('保存成功');
    }
}
在实例中,为了让大家接触更多代码编写规范,我们实现同一个功能,会采用不同的代码写法,其作用是一样的,也是方便开发者融合贯通。在这个例子中,新引入了一个Message类,这个属于通用工具类,我们会在相关章节单独介绍。
二、更新多个数据行
上述方法都可以用于单个Active Record实例,以插入或更新单条表数据行。 要同时更新多个数据行,你应该调用updateAll()方法, 这是一个静态方法。以下 操作将会把满足条件的行全部更新。
// UPDATE `goods` SET `if_show` = 1 WHERE `goods_name` LIKE `%iPhone 11%`
GoodsModel::updateAll(['if_show' => 1], ['like', 'goods_name', 'iPhone 11']);
也可以一次更新多个字段,满足多个条件,如下:
// UPDATE `goods` SET `if_show`=1, `closed`=0  WHERE `recommended`=0 AND `goods_name` LIKE `%iPhone 11%`
GoodsModel::updateAll(['if_show'=>1, 'closed'=>0], 
                      ['and', ['recommended' => 0], ['like', 'goods_name', 'iPhone 11']]
                );
三、更新计数
在数据库表中增加或减少一个字段的值是个常见的任务。我们将这些列称为“计数列”。比如我们浏览一个商品,需要给浏览量+1,不能直接使用update/save方法,需要使用updateCounters()更新一个或多个计数列。 例如:
$model = GoodsStatisticsModel::find()->where(['goods_id' => 100])->one();

// UPDATE `GoodsStatisticsModel` SET `views` = `views` + 1 WHERE `goods_id` = 100
$model->updateCounters(['views' => 1]);

// 如果是减1,则
$model->updateCounters(['views' => -1]);
注意: 如果你使用update/save更新一个计数列,你最终将得到错误的结果, 因为可能发生这种情况,多个请求间并发读写同一个计数列。
四、删除数据
要删除单行数据,首先获取与该行对应的 Active Record 实例,然后调用delete()方法,如果需要删除多行或者整个表的数据, 则使用静态方法deleteAll(),如下是在控制器中的例子:
namespace frontend\controllers\home;
use Yii;

use common\models\GoodsModel;
use common\library\Basewind;
use common\library\Message;

class GoodsController extends \common\base\BaseMallController
{
    public function actionDelete() 
    {
        // 获取欲删除的行
        $post = Basewind::trimAll(Yii::$app->request->get(), true, ['goods_id']);

        // 方式一: 
        // 获取与该行对应的 Active Record 实例
        $model = GoodsModel::find()->where(['goods_id' => $post->goods_id])->one();
        if(!$model->delete()) {
            return Message::warning($model->errors);
        }

        // 方式二:
        GoodsModel::deleteAll(['goods_id' => $post->goods_id]);
    }
}
调用deleteAll()时要非常小心,因为如果在指定条件时出错, 它可能会完全擦除表中的所有数据。另外还要注意 delete()返回Boolean,而deleteAll()返回数值型,即删除成功的行数。
有关模型的更多问题,也可以从Yii2官方文档Active Record 类获取,其所有的类名和方法都可以在ShopWind系统中使用。此外,您还可以访问我们的 开发者社区反馈,我们会有官方技术人员在线解答。