[TOC]
### 1.簡單查詢:
~~~
[[one()]]: 根據查詢結果返回查詢的第一條記錄。
[[all()]]: 根據查詢結果返回所有記錄。
[[count()]]: 返回記錄的數量。
[[sum()]]: 返回指定列的總數。
[[average()]]: 返回指定列的平均值。
[[min()]]: 返回指定列的最小值。
[[max()]]: 返回指定列的最大值。
[[scalar()]]: 返回查詢結果的第一行中的第一列的值。
[[column()]]: 返回查詢結果中的第一列的值。
[[exists()]]: 返回一個值,該值指示查詢結果是否有數據。
[[where()]]: 添加查詢條件
[[with()]]: 該查詢應執行的關系列表。
[[indexBy()]]: 根據索引的列的名稱查詢結果。
[[asArray()]]: 以數組的形式返回每條記錄。
~~~
#### 應用實例:
~~~
Customer::find()->one(); 此方法返回一條數據;
Customer::find()->all(); 此方法返回所有數據;
Customer::find()->count(); 此方法返回記錄的數量;
Customer::find()->average(); 此方法返回指定列的平均值;
Customer::find()->min(); 此方法返回指定列的最小值 ;
Customer::find()->max(); 此方法返回指定列的最大值 ;
Customer::find()->scalar(); 此方法返回值的第一行第一列的查詢結果;
Customer::find()->column(); 此方法返回查詢結果中的第一列的值;
Customer::find()->exists(); 此方法返回一個值指示是否包含查詢結果的數據行;
Customer::find()->asArray()->one(); 以數組形式返回一條數據;
Customer::find()->asArray()->all(); 以數組形式返回所有數據;
Customer::find()->where($condition)->asArray()->one(); 根據條件以數組形式返回一條數據;
Customer::find()->where($condition)->asArray()->all(); 根據條件以數組形式返回所有數據;
Customer::find()->where($condition)->asArray()->orderBy('id DESC')->all(); 根據條件以數組形式返回所有數據,并根據ID倒序;
~~~
### 2.關聯查詢:
> [[ActiveRecord::hasOne()]]:返回對應關系的單條記錄
[[ActiveRecord::hasMany()]]:返回對應關系的多條記錄
**應用場景:**
~~~
//客戶表Model:CustomerModel
//訂單表Model:OrdersModel
//國家表Model:CountrysModel
//首先要建立表與表之間的關系
//在CustomerModel中添加與訂單的關系
Class CustomerModel extends ActiveRecord
{
...
public function getOrders()
{
//客戶和訂單是一對多的關系所以用hasMany
//此處OrdersModel在CustomerModel頂部別忘了加對應的命名空間
//customer_id對應OrdersModel的customer_id字段,id對應的是CustomerModel的id字段
return $this->hasMany(OrdersModel::className(), ['customer_id'=>'id']);
}
//可以定義多個orders的關聯數據,返回價格大于100的訂單
public function getBigOrders($priceNum=100)
{
return $this->hasMany(OrdersModel::className(), ['customer_id'=>'id'])
->where('price_num>:threshold', [':threshold' => $threshold]);
}
public function getCountry()
{
//客戶和國家是一對一的關系所以用hasOne
return $this->hasOne(CountrysModel::className(), ['country_id'=>'id']);
}
....
}
~~~
#### 1.直接使用
~~~
//查詢單表數據,調用相關數據,再重新查詢SQL
$customer = CustomerModel::find();
var_dump($customer->getCountry()); //第一次使用,會進行SQL查詢
var_dump($customer->getCountry()) //第二次使用,因為被緩存了,直接調用。
//如果下一次調用$customer->getCountry()時,不想使用被緩存的數據,可以使用unset($customer->country);來清除緩存,那么下次調用則會重新執行查詢SQL。
//上面的代碼會生成如下sql語句
//SELECT * FROM customer
//SELECT * FROM country WHERE id=1;
var_dump($customer->orders); //如果以屬性的方式調用,會直接返回模型的結果
var_dump($customer->bigOrders); //關聯數據中價格大于100的訂單,
var_dump($customer->getBigOrders(200)->all()); //關聯數據中價格大于200的訂單,如果以函數的方式調用,會返回一個 ActiveQuery 對象
~~~
#### 2.使用with()
* with例子
~~~
// 在SQL中一次性級聯查詢,調用相關數據,都直接在查詢出來的數據中直接獲取
// 查詢客戶與他們的訂單和國家
$customerList = CustomerModel::find()->with('orders', 'country')->all();
foreach($customerList as $customer){
//調用時,則不會請求SQL查詢,因為已經在上一個步驟查詢并緩存好了。
var_dump($customer->orders);
var_dump($customer->country);
}
// 查詢客戶與他們的訂單和訂單的發貨地址
CustomerModel::find()->with('orders.address')->all();
// 查詢客戶與他們的國家和狀態為1的訂單
CustomerModel::find()->with([
'orders' => function ($query) {
$query->andWhere('status = 1');
},
'country',
])->all();
//1.在查詢時加了->select();如下,要加上order_id,即關聯的字段(比如:order_id)比如要在select中,否則會報錯:undefined index order_id
// 查詢客戶與他們的訂單和國家
CustomerModel::find()->select('order_id,id,name')->with('orders')->all();
~~~
* 給with加過濾條件
~~~
//1.查詢一個客戶大于100的訂單,可使用ActiveQuery方式
//首先執行sql: SELECT * FROM customer WHERE id=1
$customer = Customer::findOne(1);
// 再執行查詢訂單的sql語句:SELECT * FROM order WHERE customer_id=1 AND subtotal>100
$orders = $customer->getOrders()->where('price_num>100')->all();
//2.查詢100個客戶的,每個客戶的價格大于100的訂單
// 下面的代碼會執行sql語句:
// SELECT * FROM customer LIMIT 100
// SELECT * FROM order WHERE customer_id IN (1,2,...) AND subtotal>100
$customerList = Customer::find()->limit(100)->with([
'orders' => function($query) {
$query->andWhere('price_num>100');
},
])->all();
~~~
#### 3.使用joinWith()
~~~
// 在SQL中一次性級聯查詢,調用相關數據,都直接在查詢出來的數據中直接獲取
// 查詢客戶與他們的訂單和國家
$customerList = CustomerModel::find()->joinWith('orders')->all();
foreach($customerList as $customer){
//調用時,則不會請求SQL查詢,因為已經在上一個步驟查詢并緩存好了。
var_dump($customer->orders);
var_dump($customer->country);
}
~~~
#### 4.joinWith與with的區別
> with方式原理流程:
總共執行了2條SQL語句:
A) 先執行主表SQL:SELECT * FROM order
B) 再執行關聯表SQL:SELECT * FROM user WHERE user_id IN (1,2,...)
C) 再通過關聯表SQL數據進行內存分配到各自的主表的每條數據上。
> joinWith方式:
流程和with一樣。只有A步驟不一樣,A步驟的主表查詢出使用的是關聯SQL查詢,如SELECT * FROM order LEFT JOIN user ON order.user_id=user.id
### 3.常用案例
#### findOne()和findAll():
~~~
// 查詢key值為10的客戶
$customer = Customer::findOne(10);
$customer = Customer::find()->where(['id' => 10])->one();
// 查詢年齡為30,狀態值為1的客戶
$customer = Customer::findOne(['age' => 30, 'status' => 1]);
$customer = Customer::find()->where(['age' => 30, 'status' => 1])->one();
// 查詢key值為10的所有客戶
$customers = Customer::findAll(10);
$customers = Customer::find()->where(['id' => 10])->all();
// 查詢key值為10,11,12的客戶
$customers = Customer::findAll([10, 11, 12]);
$customers = Customer::find()->where(['id' => [10, 11, 12]])->all();
// 查詢年齡為30,狀態值為1的所有客戶
$customers = Customer::findAll(['age' => 30, 'status' => 1]);
$customers = Customer::find()->where(['age' => 30, 'status' => 1])->all();
~~~
#### where()條件:
$customers = Customer::find()->where($cond)->all();
$cond寫法舉例:
~~~
// SQL: (type = 1) AND (status = 2).
$cond = ['type' => 1, 'status' => 2]
// SQL:(id IN (1, 2, 3)) AND (status = 2)
$cond = ['id' => [1, 2, 3], 'status' => 2]
//SQL:status IS NULL
$cond = ['status' => null]
~~~
#### [[and]]:將不同的條件組合在一起,用法舉例:
~~~
//SQL:`id=1 AND id=2`
$cond = ['and', 'id=1', 'id=2']
//SQL:`type=1 AND (id=1 OR id=2)`
$cond = ['and', 'type=1', ['or', 'id=1', 'id=2']]
~~~
#### [[or]]:
~~~
//SQL:`(type IN (7, 8, 9) OR (id IN (1, 2, 3)))`
$cond = ['or', ['type' => [7, 8, 9]], ['id' => [1, 2, 3]]
~~~
#### [[not]]:
~~~
//SQL:`NOT (attribute IS NULL)`
$cond = ['not', ['attribute' => null]]
~~~
#### [[between]]: not between 用法相同
~~~
//SQL:`id BETWEEN 1 AND 10`
$cond = ['between', 'id', 1, 10]
~~~
#### [[in]]: not in 用法類似
~~~
//SQL:`id IN (1, 2, 3)`
$cond = ['in', 'id', [1, 2, 3]]
//IN條件也適用于多字段
$cond = ['in', ['id', 'name'], [['id' => 1, 'name' => 'foo'], ['id' => 2, 'name' => 'bar']]]
//也適用于內嵌sql語句
$cond = ['in', 'user_id', (new Query())->select('id')->from('users')->where(['active' => 1])]
~~~
#### [[like]]:
~~~
//SQL:`name LIKE '%tester%'`
$cond = ['like', 'name', 'tester']
//SQL:`name LIKE '%test%' AND name LIKE '%sample%'`
$cond = ['like', 'name', ['test', 'sample']]
//SQL:`name LIKE '%tester'`
$cond = ['like', 'name', '%tester', false]
~~~
#### [[exists]]: not exists用法類似
~~~
//SQL:EXISTS (SELECT "id" FROM "users" WHERE "active"=1)
$cond = ['exists', (new Query())->select('id')->from('users')->where(['active' => 1])]
~~~
此外,您可以指定任意運算符如下
~~~
//SQL:`id >= 10`
$cond = ['>=', 'id', 10]
//SQL:`id != 10`
$cond = ['!=', 'id', 10]
~~~
#### 常用查詢:
~~~
// WHERE admin_id >= 10 LIMIT 0,10
User::find()->select('*')->where(['>=', 'admin_id', 10])->offset(0)->limit(10)->all()
// SELECT `id`, (SELECT COUNT(*) FROM `user`) AS `count` FROM `post`
$subQuery = (new Query())->select('COUNT(*)')->from('user');
$query = (new Query())->select(['id', 'count' => $subQuery])->from('post');
// SELECT DISTINCT `user_id` ...
User::find()->select('user_id')->distinct();
~~~
#### 更新:
~~~
//update();
//runValidation boolen 是否通過validate()校驗字段 默認為true
//attributeNames array 需要更新的字段
$model->update($runValidation , $attributeNames);
//updateAll();
//update customer set status = 1 where status = 2
Customer::updateAll(['status' => 1], 'status = 2');
//update customer set status = 1 where status = 2 and uid = 1;
Customer::updateAll(['status' => 1], ['status'=> '2','uid'=>'1']);
~~~
#### 刪除:
~~~
$model = Customer::findOne($id);
$model->delete();
$model->deleteAll(['id'=>1]);
~~~
#### 批量插入:
~~~
Yii::$app->db->createCommand()->batchInsert(UserModel::tableName(), ['user_id','username'], [
['1','test1'],
['2','test2'],
['3','test3'],
])->execute();
~~~
#### 事務:
> 普通事務,用于與ajaxbtn結合
~~~
public function saveWithTrans(){
$transaction = Yii::$app->db->beginTransaction();
$errors = [];
try {
//1.事件一todo~~~
if(!$this->save()){
$errors = $this->errors;
throw new \Exception();
}
//2.事件二todo~~~
$arr = explode(',', $this->tag);
Tag::deleteAll(['in', 'name', $arr]);
//3.事件三todo~~~
foreach ($arr as $val){
$model = new Tag();
$model->id = CommonUtil::uuid();
$model->name = $val;
if(!$model->save()){
$errors = $model->errors;
throw new \Exception();
}
}
$transaction->commit();
} catch (\Exception $e) {
$transaction->rollBack();
}
return $errors;
}
//調用方法
if (!empty($errors = $model->saveWithTrans())) {
jsonFail($errors);
}
jsonSuccess();
//當調用該事務方法后,得到errors的返回值,如果返回值為空,則執行成功,不為空,則表示有錯誤,則可以將錯誤進行打印處理。
~~~
> API事務,常用于API調用的時候,當然AJAXBTN也能用。
~~~
public function saveWithTrans(){
$transaction = Yii::$app->db->beginTransaction();
$error = '';
try {
//1.事件一todo~~~
if(!$this->save()){
$error = firstError($this);
throw new \Exception();
}
//2.事件二todo~~~
$arr = explode(',', $this->tag);
Tag::deleteAll(['in', 'name', $arr]);
//3.事件三todo~~~
foreach ($arr as $val){
$model = new Tag();
$model->id = CommonUtil::uuid();
$model->name = $val;
if(!$model->save()){
$error = firstError($model);
throw new \Exception();
}
}
$transaction->commit();
} catch (\Exception $e) {
$transaction->rollBack();
}
return $error;
}
//調用方法
if (!empty($error = $model->saveWithTrans())) {
jsonFail($error);
}
jsonSuccess();
//當調用該事務方法后,得到error的返回值,如果返回值為空,則執行成功,不為空,則表示有錯誤,則可以將錯誤進行打印處理。
~~~
#### 查看執行sql
~~~
//UserModel
$query = UserModel::find()->where(['status'=>1]);
echo $query->createCommand()->getRawSql();
~~~
- 基礎教程
- 入門安裝
- Yii2 composer 安裝慢解決
- Cookies
- 數據庫操作
- 數據提供者
- 助手類
- 驗證規則
- GridView
- DetailView
- YII2分頁
- JS、CSS的引用
- Excel導出
- 中文轉拼音
- 發送郵件
- 第三方插件
- Session跨域共享
- Url跨域訪問
- 場景應用
- 查詢條件鏈
- Session分布式共享
- Redis的使用
- mongodb
- 高級教程
- 自定義gii模板
- 角色權限管理(RBAC)
- user組件的配置
- 國際化(I18N)
- 小部件(Widget)
- 模塊(Module)
- 行為(Behavior)
- 緩存(Cache)
- migrate 數據庫遷移
- phpstorm
- 快捷鍵
- 自定義
- 其它插件