数据库+模型 - AR模型

  • 作者:KK

  • 发表日期:2016.12.16


介绍

AR模型其实是指yii\db\ActiveRecord这个类,它是由yii\base\Model派生出来的,作用是让我们方便地操作数据里的数据

  • 提示

    Model是模型,与数据库无关

    模型在不同的应用领域是分为不同级别的,其中ORM模型是我们很经常接触的一种

    ActiveRecord是ORM模型的一种实现(ActiveRecord相关论述资料


前提准备 - 建表

既然模型是为了方便操作数据的话,咱们搞张test表来做测试吧

在配置好db组件的情况下先运行一次以下代码,它会创建一张test表:

$migrate = new \yii\db\Migration();
$migrate->createTable('test', [
	'id' => $migrate->primaryKey(),
	'name' => $migrate->string(10)->notNull()->comment('姓名'),
	'age' => $migrate->boolean()->unsigned()->defaultValue(0)->notNull()->comment('年龄'), //mysql的话底层会将boolean转换成tinyint,sqlite的话就是boolean,所以如果用sqlite请改成smallint()或integer()
]);

建立模型

接下来我们手动创建一个AR模型来操作test表(其实官方提供了一个叫gii的工具,不过我希望大家印象更深刻,齐齐来动手!

  1. 创建一个app\models\Test类,继承yii\db\ActiveRecord

  2. 定义一个名为tableName公共的静态方法,无参数,返回一个要操作的表名字符串

代码应该是这样的:

namespace app\models;

class Test extends \yii\db\ActiveRecord{
	public static function tableName(){
		return 'test';
	}
}

部署测试代码

//插入
$test = new Test([
	'name' => 'Jay',
	'age' => 18,
]);
$test->save(); //数据库会多一条记录,底层是insert
echo $test->id; //入库后的id字段自增值

//查询
$test2 = Test::findOne($test->id); //假设上面插入后ID是1,用findOne方法查出来
print_r([$test2->name, $test2->age]); //就是刚才插入的那条记录

//更新
$test2->name = 'may';
$test2->save(); //底层会update,简单地说save的时候,一般new出来的就是新的,会insert,  findOne出来的就是旧的,会update

echo (new \yii\db\Query())->from(Test::tableName())->where(['id' => $test->id])->one()['name']; //may


//删除
$test2->delete();
print_r(Test::findOne($test2->id)); //查询结果为false,因为数据库里删除了

findOne

AR模型的findOne这个静态方法是用于查找数据并转换成模型实例返回,它的参数有两种表达方式:

  1. 数据ID,就是主键

  2. 条件数组,和yii\db\Query的where数组写法一样

相当于Query对象的one方法返回一条记录的数组一样,findOne就是返回一条记录的对象,由于是对象,是对象就能有方法,有方法就能方便地执行save、delete等,以及封装更多处理逻辑


字段赋值

如果数据表里有name字段,则可以直接操作模型的name属性,像上面$test2->name这样

还可以用数组语法操作,比如$test['name'] = 'abc'; $test->save();


转成数组

Test::findOne这样查出来是个对象,可是返回给前端的要是个数组咋办,可以这样:

Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
Yii::$app->response->data = $test->toArray();

用toArray能将数据库相关的字段转换成数组来返回


查询多条记录

findOne改成findAll即可,参数和findOne一模一样

它就相当于Query对象的all方法返回多条记录的数组一样,findAll就是返回多条记录的模型数组

示例代码:

foreach(Test::findAll(['status' => 1]) as $test){
	print_r($test->name, $test->age);
}

无条件findAll就传个空数组吧,但不能不传参数


批量更新数据

updateAll方法:

Test::updateAll(['name' => 'abc'], ['id' => $ids]);
//UPDATE test SET name = abc WHERE id in ($ids)

第一个参数是要更新的字段和值

第二个参数就是条件,当然还是跟Query的where方法参数一样啦亲

不用AR模型实现更新数据的话,那就要这样来写代码了:

Yii::$app->db->createCommand()->update(Test::tableName(), $data, ['id' => $ids])

那至少,用AR模型写更新的代码会短一些,但当然AR不仅仅只是为了缩短代码的书写而存在……


实现更新 +1 之类的

要实现这样更新文章点击数量的话:(UPDATE xxxTable SET view_count = view_count + 1

updateCounters这个方法:

$article = Article::findOne(1);
$article->updateCounters(['view_count' => 1]);

key就是要累加的字段,value就是要累加的值,如果是'view_count' => 3那自然就是SET view_count = view_count + 3


批量删除数据

一样的思想,就是deleteAll方法:

Test::deleteAll(['id' => $ids]);
//DELETE FROM test WHERE id in($ids)

参数就是删除的条件