建立数据库连接
AR 用一个 DB connection 对象与数据库交换数据。默认的,它使用 db
组件作为其连接对象。详见数据库基础章节,你可以在应用程序配置文件中设置下 db
组件,就像这样,
return [
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=testdb',
'username' => 'demo',
'password' => 'demo',
],
],
];
如果在你的应用中应用了不止一个数据库,且你需要给你的 AR 类使用不同的数据库链接(DB connection),你可以覆盖掉 getDb() 方法:
class Customer extends ActiveRecord
{
// ...
public static function getDb()
{
return \Yii::$app->db2; // 使用名为 "db2" 的应用组件
}
}
查询数据
AR 提供了两种方法来构建 DB 查询并向 AR 实例里填充数据:
以上两个方法都会返回 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 对象关联的那张表中的某一行:
AR 同时提供了一下静态方法,可以应用在与某 AR 类所关联的整张表上。用这些方法的时候千万要小心,因为他们作用于整张表!比如,deleteAll()
会删除掉表里所有的记录。
- yii\db\ActiveRecord::updateCounters()
- updateAll()
- updateAllCounters()
- 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,所以它同样也支持