yii2中ar适用于单条记录增删改查及关联预加载,dao适合原始sql和批量操作;ar需判空且字段名严格匹配,dao返回原始数据需手动处理类型,事务确保多模型操作原子性。

要在 Yii2 项目中快速完成数据库读写操作,不依赖 Gii 生成代码、不重写配置、不修改底层组件,直接用原生 AR 或 DAO 实现增删改查和复杂查询,必须明确每种方式的适用边界和调用链路。
用 ActiveRecord 快速查一条记录
第一步:确保模型类已存在且正确声明 tableName() 方法,例如 User 类返回 'user' 表名。
第二步:调用 User::findOne($id) → 返回单个 AR 实例,若不存在则返回 【null】,不可直接调用属性,需先判空。
第三步:如需按字段查(如邮箱),用 User::findOne(['email' => $email]);注意此处条件数组键必须是字段名,不能是别名或表达式。
用 DAO 执行原始 SQL 查询
方法一:查单值(如统计数)
使用 \Yii::$app->db->createCommand('SELECT COUNT(*) FROM user WHERE status = :status')->bindValue(':status', 1)->queryScalar() → 返回整型数字。
方法二:查多行多列结果
执行 \Yii::$app->db->createCommand('SELECT id, name FROM user LIMIT 5')->queryAll() → 返回二维索引数组,键为数字而非字段名。
方法三:查单行关联数据\Yii::$app->db->createCommand('SELECT u.id, u.name, p.title FROM user u LEFT JOIN post p ON u.id = p.user_id WHERE u.id = :id')->bindValue(':id', 1)->queryOne() → 字段别名会保留,但不会自动映射为对象属性。
⚠️ 注意:DAO 查询结果默认不经过模型验证和类型转换,时间戳、布尔值等可能为字符串或原始数据库值,需自行处理。
AR 关联查询与懒加载控制
① 在 User 模型中定义 getPosts() 关系方法:public function getPosts() { return $this->hasMany(Post::class, ['user_id' => 'id']); }
② 查询用户并预加载文章列表:$user = User::find()->with('posts')->where(['id' => 1])->one(); → 此时 $user->posts 是已查出的 AR 对象数组,不会触发二次查询。
③ 若只查用户、后续才需要文章,直接访问 $user->posts 将触发懒加载,执行额外 SQL;这在循环中极易引发 N+1 查询问题。
④ 禁用懒加载可在配置中全局关闭:'enableSchemaCache' => true 仅缓存表结构,不影响关联行为;真正禁用懒加载需在模型中设置 public static $lazyLoading = false; —— 但该属性 Yii2 原生不支持,【必须手动覆盖 __get() 方法或改用 eager loading】。
批量插入与事务安全写入
方法1:单条 AR 插入$user = new User(); $user->name = 'Alice'; $user->email = 'a@b.c'; $user->save(); → 成功返回 true,失败返回 false,错误信息在 $user->errors 中。
方法2:DAO 批量插入(高效)\Yii::$app->db->createCommand()->batchInsert('user', ['name', 'email'], [['Tom', 't@b.c'], ['Jerry', 'j@b.c']])->execute(); → 返回插入行数,不校验模型规则。
方法3:事务包裹多模型操作\Yii::$app->db->transaction(function ($db) { $order = new Order(); $order->save(); $item = new OrderItem(); $item->order_id = $order->id; $item->save(); }); → 任意一步失败自动回滚,无需手动 try/catch。











