最近一直在看網上視頻學習Yii2.0,剛學習了關聯查詢這一章,就把自己的學習筆記總結了一下。關聯查詢在實際中用的是比較多的,其實在關聯查詢中,還有幾個小的知識點需要注意,比如:hasMany和hasOne,joinWith 和 with的區別等,如果有理解不正確的地方,歡迎指正!
1.表的關聯設計
a)Customer表
—-id 用戶ID
—-name 用戶名
b)Order表
—-id 價格ID
—-customer_id 用戶ID
—-price 價格
customer表中的id 和Order表中的 customer_id 是關聯的
2.在models中的寫法
a)在customer表中加上方法getOrders();(這個方法中的get是固定的,而Orders是可以隨便取的,但是我們一般傾向於和表名一致);
public function getOrders(){
$orders=$this->hasMany(Order::className(),['customer_id'=>'id'])->asArray()->all();
return $orders;
}
b)在price表中加上方法getCustomer();
public function getCustomer(){
$customer=$this->hasOne(Customer::className(),['id'=>'customer_i d'])->asArray()->one();
return $customer;
}
注意:在兩個模型類中,你會發現getOrders方法中用的是hasMany,而在getCustomer方法中用的是hasOne,他們有什麼區別呢?
i.通過customer來查詢order,一個顧客可能會有多個訂單,所以就調用的是hasMany(),所以說,hasMany 就是用於一對多的情況;
ii.通過訂單來查詢顧客,一個訂單隻能屬於一個顧客,所以就調用的是hasOne(),所以說,hasOne 就是用於一對一的情況;
3.在Controllers中調用的寫法
a)通過顧客查詢訂單:
public function actionOrder(){
//查新顧客信息
$customer=Customer::find()->where(['name'=>'zhangsan'])->one();
//查詢出張三對應的所有訂單
$orders=$customer->getOrders();
var_dump($orders);
}
注意:以上$orders=$customer->getOrders();這行代碼也可以寫爲:$orders=$customer->orders;(這個orders就是models中的getorders中的orders),不過如果這樣寫的話,model中的方法最後的all()或one,方法就不能調用了,因爲我們這樣用時,$orders=$customer->orders;它會根據我們model中的hasMany 和 hasOne在後邊自動補全all 或 one.
b)通過訂單查詢顧客:
public function actionCustomer(){
//查詢出訂單
$order=Order::find()->where(['id'=>1])->one();
//查詢出顧客
$cus=$price->getCustomer();
var_dump($cus);
}
c)其實在控制器中我們也可以直接寫成以下形式:
public function actionOrder(){
$customer=Customer::find()->where(['name'=>'zhangsan'])->one();
$orders=$customer->hasMany(Price::className(),['customer_id'=>'id'])->asArray()->all();
$orders=$customer->getOrders();
}
就是把model中封裝的那個方法直接寫在控制器中,但是這樣寫有個缺陷,就是當我們的表名或關聯字段發生改變的時候,就需要修改控制器,如果我們在多個控制器中都查詢了,修改起來就比較複雜,封裝在models中之後,就直接修改對應的model就ok了。
4.關聯查詢的性能問題
a)關聯查詢的多次查詢
//查詢出所有的customer
$customer=Customer::find()->all();//select * from customer
foreach($customers as $customer){
//把每個顧客對應的訂單都查詢出來
$orders[]=$customer->orders;//=>select * from order where customer_id =....如果是100個customer,就要調用100次查詢
}
以上的寫法,如果是100個顧客,就會查詢數據庫101次,查用戶一次,根據用戶查訂單100次
b)優化
$customers=Customer::find()->with('orders')->all();
//這樣優化之後,相當於:
select * from customer
select * from orders where customer_id in (....);
之前要查詢101次的,現在只需要查詢2次就可以了
注意:with 中的“orders”,也是model中的getOrders中的orders