AR类是yii2中常用的数据库操作类(还有一种DAO模式,基于sql语句查询),是一种对象化的数据库操作模式,每一个AR类关联着一张数据表,每个AR对象对应着数据表中的一行,对象的每个属性对应着该行的相应列,这样就可以以面向对象的方式操作数据表的数据,而不用写sql语句了。
初始化
constructor
init(): will trigger an EVENT_INIT event
save调用时
beforeValidate(): //return bool
afterValidate(): will trigger an EVENT_AFTER_VALIDATE event
beforeSave(): will trigger an EVENT_BEFORE_INSERT or EVENT_BEFORE_UPDATE event
perform the actual data insertion or updating
afterSave(): will trigger an EVENT_AFTER_INSERT or EVENT_AFTER_UPDATE event
delete调用时
beforeDelete(): will trigger an EVENT_BEFORE_DELETE event
perform the actual data deletion
afterDelete(): will trigger an EVENT_AFTER_DELETE event
更改不同数据表
如果你的yii2工程用到了1个以上数据库,在相应的应用目录中配置多个的数据库,然后在相应的基于AR类的数据表中重写的getDb覆盖父类的方法,以达到更换不同的数据表。
return [
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=testdb1',
'username' => 'demo1',
'password' => 'demo1',
],
'db2' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=testdb2',
'username' => 'demo2',
'password' => 'demo2',
],
],
];
class OcButlerTask extends \yii\db\ActiveRecord
{
//...
public static function getDb()
{
return \Yii::$app->db2; // 使用名为 "db2" 的应用组件
}
}
数据常用操作
数据表创建保存:
public function actionCreate()
{
$model = new OcButlerTask();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
Model类的load函数通过请求的参数,将post请求的key=>value赋值给创建的OcButlerTask类的属性。因AR类也是基于Model类的,在Model类的setAttributes函数中将post参数相应的值传递给OcButlerTask的属性。
通过BaseActiveRecord类的save函数,将数据保存在数据表中,通过_oldAttributes属性是否为空判断保存的数据是新创建的还是需要更改的数据。save时会根据你的ar类定义的rules规则去检测相应数据的格式是否正确,若都满足则save返回true表示数据保存成功,false保存失败。保存失败可通过VarDumper::dumpAsString捕捉失败异常。
public function save($runValidation = true, $attributeNames = null)
{
if ($this->getIsNewRecord()) {
return $this->insert($runValidation, $attributeNames);
} else {
return $this->update($runValidation, $attributeNames) !== false;
}
}
if (!$model->save()) {
throw new \Exception("失败原因:\n".VarDumper::dumpAsString($model->getErrors()), 500);
}
常用的查询操作:
//查询id为指定的$task_id的OcButlerTask类
/** @var OcButlerTask $task */
$task = OcButlerTask::find()
->where(['id' => $task_id])
->one();
//查询所有已完成的任务,并以id排序
$tasks = OcButlerTask::find()
->where(['status' => OcButlerTask::BUTLER_TASK_COMPLETE])
->orderBy('id')
->all();
//返回所有已完成任务的数量
$task_count = OcButlerTask::find()
->where(['status' => OcButlerTask::BUTLER_TASK_COMPLETE])
->count();
//以sql语句查询,返回所有的任务
$tasks = OcButlerTask::findBySql("select * from oc_butler_task")
->all();
//查询id为指定的$task_id的OcButlerTask类,以数组方式返回。
$task = OcButlerTask::find()
->where(['id' => $task_id])
->asArray()
->one();
//快捷方法,返回id为1的任务。
$task = OcButlerTask::findOne(1);
//快捷方法,返回所有状态已完成的任务
$tasks = OcButlerTask::findAll([
'status' => OcButlerTask::BUTLER_TASK_COMPLETE,
]);
//批量操作,用于数据量大时,返回所有数据需要分配的内存太大等问题
// 一次提取10个任务
foreach (OcButlerTask::find()->batch(10) as $tasks) {
// $tasks是10个或更少的客户对象的数组
}
// 一次提取10个客户并一个一个地遍历处理
foreach (OcButlerTask::find()->each(10) as $task) {
// $task是一个‘OcButlerTask’对象
}
// 贪婪加载模式的批处理查询
foreach (OcButlerTask::find()->with('orders')->each() as $task) {
}
数据的更改删除:
//数据更改保存
$task= OcButlerTask::findOne($id);
$task->status = OcButlerTask::BUTLER_TASK_ASSIGN;
$task->save();
// 数据删除
$task= OcButlerTask::findOne($id);
$task->delete();
// 删除所有成功的管家任务
Customer::deleteAll('status = :status', [':status' => OcButlerTask::BUTLER_TASK_COMPLETE]);
关联查询
我们在使用migrate创建数据表时,对与创建表使用FOREIGN KEY外联另一张表的id时,经常在使用gii生成相应的model类时会发现,对于外联的表的键会生成相应的关联查询方法。
$this->execute("
CREATE TABLE IF NOT EXISTS {{oc_butler_task}}
(
[[id]] INT NOT NULL AUTO_INCREMENT,
[[butler_id]] INT ,
[[user_name]] VARCHAR(32) ,
[[tel_num]] VARCHAR(20),
[[create_at]] TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
[[update_at]] TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
[[status]] INT NOT NULL DEFAULT 0,
PRIMARY KEY ([[id]]),
FOREIGN KEY ([[butler_id]]) REFERENCES {{oc_butler}}([[id]]),
)DEFAULT CHARSET=utf8;
");
对应OcButlerTask类中的关联方法
public function getButler()
{
return $this->hasOne(OcButler::className(), ['id' => 'butler_id']);
}
以上使用了AR类中的hasOne()方法,该表时关联数据一对一的关系模型,一个管家任务对应着一个管家负责。hasOne返回的是一个ActiveQuery对象,通过ActiveQuery类的one方法找到对应的OcButler类(对应的管家AR类)
$task->getButler()->one()
//获取到对应管家id的Butler类,就可以操作对应的Butler表了。
其它的关联操作还有很多,有需要的可以查找相应的API方法。参考API