反向关联(Inverse Relations)
两个 Active Record 类之间的关联声明往往是相互关联的。例如,Customer 是
通过 orders 关联到 Order ,而Order 通过 customer 又关联回到了 Customer。
class Customer extends ActiveRecord
{
public function getOrders()
{
return $this->hasMany(Order::className(), ['customer_id' => 'id']);
}
}
class Order extends ActiveRecord
{
public function getCustomer()
{
return $this->hasOne(Customer::className(), ['id' => 'customer_id']);
}
}
现在考虑下面的一段代码:
// SELECT * FROM `customer` WHERE `id` = 123
$customer = Customer::findOne(123);
// SELECT * FROM `order` WHERE `customer_id` = 123
$order = $customer->orders[0];
// SELECT * FROM `customer` WHERE `id` = 123
$customer2 = $order->customer;
// 显示 "not the same"
echo $customer2 === $customer ? 'same' : 'not the same';
我们原本认为 $customer 和 $customer2 是一样的,但不是!其实他们确实包含相同的
客户数据,但它们是不同的对象。 访问 $order->customer 时,需要执行额外的 SQL 语句,
以填充出一个新对象 $customer2。
为了避免上述例子中最后一个 SQL 语句被冗余执行,我们应该告诉 Yii
customer 是 orders 的 反向关联,可以通过调用 inverseOf() 方法声明,
如下所示:
class Customer extends ActiveRecord
{
public function getOrders()
{
return $this->hasMany(Order::className(), ['customer_id' => 'id'])->inverseOf('customer');
}
}
这样修改关联声明后:
// SELECT * FROM `customer` WHERE `id` = 123
$customer = Customer::findOne(123);
// SELECT * FROM `order` WHERE `customer_id` = 123
$order = $customer->orders[0];
// No SQL will be executed
$customer2 = $order->customer;
// 输出 "same"
echo $customer2 === $customer ? 'same' : 'not the same';