💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
### 新增数据 用 AR 而不是原生的 SQL 语句去执行数据库查询,可以调用直观方法来实现相同目标。如,调用 yii\db\ActiveRecord::save() 方法将执行插入或更新轮询,将在该 AR 类关联的数据表新建或更新一行数据: $customer = new Customer(); $customer->name = 'Qiang'; $customer->save(); // 一行新数据插入 customer 表 上面的代码和使用下面的原生 SQL 语句是等效的,但显然前者更直观, 更不易出错,并且面对不同的数据库系统(DBMS, Database Management System)时更不容易产生兼容性问题。 $db->createCommand('INSERT INTO customer (name) VALUES (:name)', [ ':name' => 'Qiang', ])->execute() ### 查询数据 声明 AR 类 要想声明一个 AR 类,你需要扩展 yii\db\ActiveRecord 基类, 并实现 tableName 方法,返回与之相关联的的数据表的名称: namespace app\models; use yii\db\ActiveRecord; class Customer extends ActiveRecord { /** * @return string 返回该AR类关联的数据表名 */ public static function tableName() { return 'customer'; } } #### 访问列数据 AR 把相应数据行的每一个字段映射为 AR 对象的一个个特性变量(Attribute) 一个特性就好像一个普通对象的公共属性一样(public property)。 特性变量的名称和对应字段的名称是一样的,且大小姓名。 使用以下语法读取列的值: // "id" 和 "mail" 是 $customer 对象所关联的数据表的对应字段名 $id = $customer->id; $email = $customer->email; 要改变列值,只要给关联属性赋新值并保存对象即可: $customer->email = 'james@example.com'; $customer->save(); 建立数据库连接 AR 用一个 yii\db\Connection 对象与数据库交换数据。 默认的,它使用 db 组件作为其连接对象。详见数据库基础章节, 你可以在应用程序配置文件中设置下 db 组件,就像这样, return [ 'components' => [ 'db' => [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=testdb', 'username' => 'demo', 'password' => 'demo', ], ], ]; 如果在你的应用中应用了不止一个数据库,且你需要给你的 AR 类使用不同的数据库链接(DB connection) ,你可以覆盖掉 yii\db\ActiveRecord::getDb() 方法: class Customer extends ActiveRecord { // ... public static function getDb() { return \Yii::$app->db2; // 使用名为 "db2" 的应用组件 } } #### 查询数据 AR 提供了两种方法来构建 DB 查询并向 AR 实例里填充数据: yii\db\ActiveRecord::find() yii\db\ActiveRecord::findBySql() 以上两个方法都会返回 yii\db\ActiveQuery 实例,该类继承自yii\db\Query, 因此,他们都支持同一套灵活且强大的 DB 查询方法,如where(),join(),orderBy(),等等。 下面的这些案例展示了一些可能的玩法: // 取回所有活跃客户(状态为 *active* 的客户)并以他们的 ID 排序: $customers = Customer::find() ->where(['status' => Customer::STATUS_ACTIVE]) ->orderBy('id') ->all(); // 返回ID为1的客户: $customer = Customer::find() ->where(['id' => 1]) ->one(); // 取回活跃客户的数量: $count = Customer::find() ->where(['status' => Customer::STATUS_ACTIVE]) ->count(); // 以客户ID索引结果集: $customers = Customer::find()->indexBy('id')->all(); // $customers 数组以 ID 为索引 // 用原生 SQL 语句检索客户: $sql = 'SELECT * FROM customer'; $customers = Customer::findBySql($sql)->all(); 小技巧:在上面的代码中,Customer::STATUS_ACTIVE 是一个在 Customer 类里定义的常量。(译注:这种常量的值一般都是tinyint)相较于直接在代码中写死字符串或数字,使用一个更有意义的常量名称是一种更好的编程习惯。 *有两个快捷方法:findOne 和 findAll() 用来返回一个或者一组ActiveRecord实例。前者返回第一个匹配到的实例,后者返回所有。 例如: * // 返回 id 为 1 的客户 $customer = Customer::findOne(1); // 返回 id 为 1 且状态为 *active* 的客户 $customer = Customer::findOne([ 'id' => 1, 'status' => Customer::STATUS_ACTIVE, ]); // 返回id为1、2、3的一组客户 $customers = Customer::findAll([1, 2, 3]); // 返回所有状态为 "deleted" 的客户 $customer = Customer::findAll([ 'status' => Customer::STATUS_DELETED, ]); *以数组形式获取数据 * 有时候,我们需要处理很大量的数据,这时可能需要用一个数组来存储取到的数据, 从而节省内存。你可以用 asArray() 函数做到这一点: // 以数组而不是对象形式取回客户信息: $customers = Customer::find() ->asArray() ->all(); // $customers 的每个元素都是键值对数组 批量获取数据 在 Query Builder(查询构造器) 里,我们已经解释了当需要从数据库中查询大量数据时,你可以用 *batch query(批量查询)*来限制内存的占用。 你可能也想在 AR 里使用相同的技巧,比如这样…… // 一次提取 10 个客户信息 foreach (Customer::find()->batch(10) as $customers) { // $customers 是 10 个或更少的客户对象的数组 } // 一次提取 10 个客户并一个一个地遍历处理 foreach (Customer::find()->each(10) as $customer) { // $customer 是一个 ”Customer“ 对象 } // 贪婪加载模式的批处理查询 foreach (Customer::find()->with('orders')->each() as $customer) { } 操作数据 AR 提供以下方法插入、更新和删除与 AR 对象关联的那张表中的某一行: yii\db\ActiveRecord::save() yii\db\ActiveRecord::insert() yii\db\ActiveRecord::update() yii\db\ActiveRecord::delete() AR 同时提供了一下静态方法,可以应用在与某 AR 类所关联的整张表上。 用这些方法的时候千万要小心,因为他们作用于整张表! 比如,deleteAll() 会删除掉表里所有的记录。 yii\db\ActiveRecord::updateCounters() yii\db\ActiveRecord::updateAll() yii\db\ActiveRecord::updateAllCounters() yii\db\ActiveRecord::deleteAll() 下面的这些例子里,详细展现了如何使用这些方法: // 插入新客户的记录 $customer = new Customer(); $customer->name = 'James'; $customer->email = 'james@example.com'; $customer->save(); // 等同于 $customer->insert(); // 更新现有客户记录 $customer = Customer::findOne($id); $customer->email = 'james@example.com'; $customer->save(); // 等同于 $customer->update(); // 删除已有客户记录 $customer = Customer::findOne($id); $customer->delete(); // 删除多个年龄大于20,性别为男(Male)的客户记录 Customer::deleteAll('age > :age AND gender = :gender', [':age' => 20, ':gender' => 'M']); // 所有客户的age(年龄)字段加1: Customer::updateAllCounters(['age' => 1]); 须知:save() 方法会调用 insert() 和 update() 中的一个, 用哪个取决于当前 AR 对象是不是新对象(在函数内部,他会检查 yii\db\ActiveRecord::isNewRecord 的值)。 若 AR 对象是由 new 操作符 初始化出来的,save() 方法会在表里插入一条数据; 如果一个 AR 是由 find() 方法获取来的, 则 save() 会更新表里的对应行记录。 数据输入与有效性验证 由于AR继承自yii\base\Model,所以它同样也支持Model的数据输入、验证等特性。例如,你可以声明一个rules方法用来覆盖掉yii\base\Model::rules()里的;你也可以给AR实例批量赋值;你也可以通过调用yii\base\Model::validate()执行数据验证。 当你调用 save()、insert()、update() 这三个方法时,会自动调用yii\base\Model::validate()方法。如果验证失败,数据将不会保存进数据库。 下面的例子演示了如何使用AR 获取/验证用户输入的数据并将他们保存进数据库: // 新建一条记录 $model = new Customer; if ($model->load(Yii::$app->request->post()) && $model->save()) { // 获取用户输入的数据,验证并保存 } // 更新主键为$id的AR $model = Customer::findOne($id); if ($model === null) { throw new NotFoundHttpException; } if ($model->load(Yii::$app->request->post()) && $model->save()) { // 获取用户输入的数据,验证并保存 } 读取默认值 你的表列也许定义了默认值。有时候,你可能需要在使用web表单的时候给AR预设一些值。如果你需要这样做,可以在显示表单内容前通过调用loadDefaultValues()方法来实现: php $customer = new Customer(); $customer->loadDefaultValues(); // ... 渲染 $customer 的 HTML 表单 ... AR的生命周期 理解AR的生命周期对于你操作数据库非常重要。生命周期通常都会有些典型的事件存在。对于开发AR的behaviors来说非常有用。 当你实例化一个新的AR对象时,我们将获得如下的生命周期: constructor yii\db\ActiveRecord::init(): 会触发一个 yii\db\ActiveRecord::EVENT_INIT 事件 当你通过 yii\db\ActiveRecord::find() 方法查询数据时,每个AR实例都将有以下生命周期: constructor yii\db\ActiveRecord::init(): 会触发一个 yii\db\ActiveRecord::EVENT_INIT 事件 yii\db\ActiveRecord::afterFind(): 会触发一个 yii\db\ActiveRecord::EVENT_AFTER_FIND 事件 当通过 yii\db\ActiveRecord::save() 方法写入或者更新数据时, 我们将获得如下生命周期: yii\db\ActiveRecord::beforeValidate(): 会触发一个 yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE 事件 yii\db\ActiveRecord::afterValidate(): 会触发一个 yii\db\ActiveRecord::EVENT_AFTER_VALIDATE 事件 yii\db\ActiveRecord::beforeSave(): 会触发一个 yii\db\ActiveRecord::EVENT_BEFORE_INSERT 或 yii\db\ActiveRecord::EVENT_BEFORE_UPDATE 事件 执行实际的数据写入或更新 yii\db\ActiveRecord::afterSave(): 会触发一个 yii\db\ActiveRecord::EVENT_AFTER_INSERT 或 yii\db\ActiveRecord::EVENT_AFTER_UPDATE 事件 最后,当调用 yii\db\ActiveRecord::delete() 删除数据时, 我们将获得如下生命周期: yii\db\ActiveRecord::beforeDelete(): 会触发一个 yii\db\ActiveRecord::EVENT_BEFORE_DELETE 事件 执行实际的数据删除 yii\db\ActiveRecord::afterDelete(): 会触发一个 yii\db\ActiveRecord::EVENT_AFTER_DELETE 事件