## Yii2開發小技巧
[TOC]
工作中或多或少會用到的關于 Yii2 的小技巧的一個總結,包括model、controller、view或者配置文件的一些寫法。
### 模型相關
#### 獲取查詢SQL
```php
$query = User::find()->where(['LIKE', 'name', 'ad%', false]);
$commandQuery = clone $query;
echo $commandQuery->createCommand()->getRawSql(); // SELECT * FROM `user` WHERE `name` LIKE 'ad%'
```
#### 查詢數據表中具體列
```php
return \yii\helpers\ArrayHelper::getColumn(User::find()->all(), 'name');
return User::find()->select('name')->asArray()->column();
```
#### `Expression()`函數
* 使用`find_in_set()`等函數,需要用到`Expression()` 表達式。
```php
User::find()
->where(new yii\db\Expression('FIND_IN_SET(:status, status)'))
->addParams([':status' => 1])
->all();
```
* 避免select里的子查詢被識別成字段
```php
$quert = User::find()
->select([
new Expression('count(*) as count , count(distinct mobile) as mnumber')
])->asArray()
->all();
```
#### 模型中事務編寫
```php
Yii::$app->db->transaction(function() {
$order = new Order($customer);
$order->save();
$order->addItems($items);
});
// 這相當于下列冗長的代碼:
$transaction = Yii::$app->db->beginTransaction();
try {
$order = new Order($customer);
$order->save();
$order->addItems($items);
$transaction->commit();
} catch (\Exception $e) {
$transaction->rollBack();
throw $e;
}
```
#### Model 里 rules 聯合唯一規則
即建立了聯合唯一索引的字段,驗證時保證數據的完整。
```php
[['store_id', 'member_name'], 'unique', 'targetAttribute' => ['store_id', 'member_name'], 'message' => 'The combination of Store ID and Member Name has already been taken.'],
```
#### 是否存在的規則
校驗 `country_id` 在 `Country` 中是否存在,一般用于一些外鍵關聯的數據表之間的數據約束。
```php
public function rules()
{
return [
[['country_id'], 'exist', 'skipOnError' => true, 'targetClass' => Country::className(), 'targetAttribute' => ['country_id' => 'id'],'message' => '此{attribute}不存在。'],
];
}
```
#### 表單驗證兩個字段選取一個
```php
public function rules()
{
return [
[['card_id', 'card_code'], function ($attribute, $param) { //至少要一個
if (empty($this->card_code) && empty($this->card_id)) {
$this->addError($attribute, 'card_id/card_code至少要填一個');
}
}, 'skipOnEmpty' => false],
];
}
```
#### Like 模糊查詢
```php
$query = User::find()->where(['LIKE', 'name', 'ad%', false]); // SELECT * FROM `user` WHERE `name` LIKE 'ad%'
```
#### 執行SQL查詢并緩存結果
調用`yii\db\Connection`的cache方法,寫入回調函數執行SQL查詢并緩存結果。
```php
$id = Yii::$app->request->get('id');
$collection = Yii::$app->db->cache(function (Connection $db) use($id){
return self::findOne(['id'=>$id]);
},10); // 緩存10秒
var_dump($collection);
```
#### `and`和`or`共用
在查詢時,`and`和`or`條件共用。
```php
Topic::updateAll(
['last_comment_time' => new Expression('created_at')],
// ['or', ['type' => Topic::TYPE, 'last_comment_username' => ''], ['type' => Topic::TYPE, 'last_comment_username' => null]]
['and', ['type' => Topic::TYPE], ['or', ['last_comment_username' => ''], ['last_comment_username' => null]]]
);
```
#### 嵌套查詢
```
$subQuery = new Query();
$subQuery->from(PostComment::tableName())->where(['status' => PostComment::STATUS_ACTIVE])->orderBy(['created_at' => SORT_DESC]);
$comment = PostComment::find()->from(['tmpA' => $subQuery])
->groupBy('post_id')
->all();
```
> 生成如下語句:`SELECT * FROM (SELECT * FROM `post_comment` WHERE `status`=1 ORDER BY `created_at` DESC) `tmpA` GROUP BY `post_id``
* * * * *
### 控制器相關
#### 獲取模塊/控制器/動作的id
```
$this->module->id
$this->id
$this->action->id
```
#### 表單提交失敗調試
```php
echo array_values($model->getFirstErrors())[0];exit;
```
#### 文件下載
存在一個文件地址,關于一些下載需要的header頭信息Yii2已經幫我們完成,如下操作即可。
```
public function actionDownload($id)
{
$model = $this->findModel($id);
if ($model) {
// do something
}
return \Yii::$app->response->setDownloadHeaders($model->downurl);
}
```
> 模型的`downurl`屬性可以通過 `extraFields()`進行設置。
#### 打印數據
```php
\yii\helpers\VarDumper::dump($var);
\yii\helpers\VarDumper::dump($var, 10 ,true);die; // 使用2 第二個參數是數組的深度 第三個參數是是否顯示代碼高亮(默認不顯示)
```
#### 控制器調用其他控制器方法
```php
Yii::$app->runAction('new_controller/new_action', $params);
// 或者
return (new SecondController('second', Yii::$app->module))->runAction('index', $data);
```
#### 獲取GET數據
```php
Yii::$app->getRequest()->get('id');
```
* * * * *
### 視圖相關
#### 視圖中獲取當前模塊/控制器/方法id
```php
Yii::$app->controller->module->id;
Yii::$app->controller->id
Yii::$app->controller->action->id
```
### 防止SQL注入或者XSS攻擊
```php
echo yii\helpers\Html::encode($view_hello_str) // 可以原樣顯示<script></script>代碼,但不解析
echo yii\helpers\HtmlPurifier::process($view_hello_str) // 可以過濾掉<script></script>代碼
```
* * * * *
### 配置相關
#### 用戶組件登錄修改
修改登陸狀態超時時間(到期后自動退出登陸) `config/web.php`中的**components**組件數組中。
```
'user' => [
'class'=>'yii\web\User',
'identityClass' => 'common\models\User',
'loginUrl'=>['/user/sign-in/login'],
'authTimeout' => 1800, // 登陸有效時間
'as afterLogin' => 'common\behaviors\LoginTimestampBehavior'
],
```
#### 配置文件IP白名單
通過下面的IP地址方式配置debug的顯示,便于調試代碼。
```
$config['modules']['debug'] = [
'class' => 'yii\debug\Module',
'allowedIPs' => ['127.0.0.1', '192.168.0.*', '192.168.33.1'],
];
```
- 開始
- Yii2開發小技巧
- Yii2使用不同的方式進行郵件發送邏輯處理
- Yii2 Serialization of 'Closure' is not allowed 錯誤
- Yii創建應用
- Yii應用結構和流程
- Yii的路徑別名
- Yii的請求
- Yii的響應
- Sessions 和 Cookies
- Yii自定義全局工具函數
- Yii2模型
- Yii2視圖
- Yii2控制器
- 大數據節省內存處理
- 關聯查詢hasMany、hasOne
- Yii2 URL地址美化
- Yii2整合AdminLTE后臺主題
- Yii2模型中的場景
- Yii2中的RBAC
- Yii2項目后臺整合yii2-admin模塊
- RBAC集成AdminLTE后臺主題對菜單進行控制
- Yii2自定義Gii模板
- 修復AdminLTE引用外部字體文件導致訪問變慢的情況
- Yii2事件簡單使用
- Yii2模型事件
- Yii2使用GridView新增操作按鈕
- Yii2向loyout模板文件中傳值
- Yii2數據緩存
- Yii2緩存
- Yii2數據緩存之增刪改查
- Yii2拓展
- Yii2日期時間插件-datetimepicker
- kartik-v/yii2-widget-fileinput上傳插件