一、不經過日誌獲取AR執行的原生SQL語句和打印變量數據php
$query = User::find() ->select(['username'])->where(['id'=>[1,2,3,4]) // get the AR raw sql in YII2 $commandQuery = clone $query; echo $commandQuery->createCommand()->getRawSql();$users = $query->all();
打印變量數據能夠這樣寫:
//引用命名空間 use yii\helpers\VarDumper; //使用 VarDumper::dump($var); //使用2 第二個參數是數組的深度 第三個參數是是否顯示代碼高亮(默認不顯示) VarDumper::dump($var, 10 ,true);
二、從數據庫二維數組中返回一維數組並配合rules驗證規則實現分類數據過濾。css
普通返回表記錄的二維數組html
Member::find()->select('userid')->asArray()->all();
Array ( [0] => Array ( [userid] => 1 ) [1] => Array ( [userid] => 2 ) [2] => Array ( [userid] => 3 ) )
返回字段的一維數組nginx
Member::find()->select('userid')->asArray()->column();
或者:web
\yii\helpers\ArrayHelper::getColumn(Member::find()->all(), 'userid')
Array ( [0] => 1 [1] => 2 [2] => 3 )
返回一維數組配合驗證規則驗證數據正確性,如分類catid正確分爲只有1-4,可是在devTools打開修改catid爲5,提交一樣會到數據庫,此時rules驗證規則以下:ajax
['catid', 'in', 'range' => category::find()->select('id')->asArray()->column()],
固然,這個也能夠經過下面這樣子寫,同樣的:sql
['catid', 'in', 'range' => \yii\helpers\ArrayHelper::getColumn(category::find()->all(), 'catid')],
這樣就能夠過濾不正確的分類數據了!數據庫
三、友好時間表示方法json
以前一直使用自定義的友好時間函數。幾天前發現萬能的YII已經提供了友好時間訪問,代碼以下:數組
Yii::$app->formatter->asRelativeTime('1447565922'); //2小時前
四、使用不一樣的響應類型或者自定義響應類型
有效的格式:
FORMAT_RAW
FORMAT_HTML
FORMAT_JSON
FORMAT_JSONP
FORMAT_XML
JSON響應
public function actionIndex() { \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; $items = ['some', 'array', 'of', 'data' => ['associative', 'array']]; return $items; }
返回:
{
"0": "some", "1": "array", "2": "of", "data": ["associative", "array"] }
自定義響應格式
讓咱們建立一個定製的響應格式。例子作點有趣和瘋狂的事我返回PHP 數組。 首先,咱們須要格式化程序自己。建立 components/PhpArrayFormatter.php:
<?php namespace app\components; use yii\helpers\VarDumper; use yii\web\ResponseFormatterInterface; class PhpArrayFormatter implements ResponseFormatterInterface { public function format($response) { $response->getHeaders()->set('Content-Type', 'text/php; charset=UTF-8'); if ($response->data !== null) { $response->content = "<?php\nreturn " . VarDumper::export($response->data) . ";\n"; } } }
組件配置:
return [ // ... 'components' => [ // ... 'response' => [ 'formatters' => [ 'php' => 'app\components\PhpArrayFormatter', ], ], ], ];
如今是準備使用。在 controllers/SiteController 建立一個新的方法 actionTest:
public function actionTest() { Yii::$app->response->format = 'php'; return [ 'hello' => 'world!', ]; }
返回以下:
<?php return [ 'hello' => 'world!', ];
五、AR入庫前時間經過在模型重寫behaviors方法實現優雅入庫方式。
以下:
public function behaviors() { return [ 'timestamp' => [ 'class' => TimestampBehavior::className(), 'attributes' => [ ActiveRecord::EVENT_BEFORE_INSERT => 'creation_time', ActiveRecord::EVENT_BEFORE_UPDATE => 'update_time', ], 'value' => function() { return date('U'); // unix timestamp }, ], ]; }
六、除配置組件記錄不一樣級別日誌外,也能夠自定義在某個地方記錄LOG日誌
use yii\log\Logger; \Yii::getLogger()->log('User has been created', Logger::LEVEL_INFO);
七、 ActiveForm類不讓生成label標籤
//方法一,經過ActiveForm類 $form->field($model, '字段名')->passwordInput(['maxlength' => true])->label(false) ?>
//方法二,經過 HTML類 Html::activeInput($type,$model,'字段名')
Yii2給必填項加星,樣式以下:
div.required label:after { content: " *"; color: red; }
八、Yii2 獲取接口傳過來的 JSON 數據:
接收get和post的數據很容易,那麼接收json數據呢?!不要緊,看這裏:
Yii::$app->request->rawBody;
九、座機和手機號碼必須填寫一個:
public function rules() { return [ [['telephone', 'mobile'], function ($attribute, $param) {//至少要一個 if (empty($this->telephone) && empty($this->mobile)) { $this->addError($attribute, 'telephone/mobile至少要填一個'); } }, 'skipOnEmpty' => false], ]; }
十、where多條件查詢示例:
//and複雜示例: $time = time(); Member::find()->where(['and', ['userid' => 1, 'company' =>'測試公司'], ['>', 'addtime', $time]]); //SELECT * FROM `member` WHERE ((`userid`=1) AND (`company`='測試公司')) AND (`addtime` > 1447587486)
//and和or組合示例: $query = Member::find()->where(['and', ['>','userid',2], ['or', ['company' => '深圳市新民傢俱備限公司'], ['address' => '深圳']]]); //SELECT * FROM `member` WHERE (`userid` > 2) AND ((`company`='深圳市新民傢俱備限公司') OR (`address`='深圳'))
十一、關於事務:
優雅的寫法
Yii::$app->db->transaction(function() { $order = new Order($customer); $order->save(); });
這至關於下列冗長的代碼:
$transaction = Yii::$app->db->beginTransaction();
try { $order = new Order($customer); $order->save(); $transaction->commit(); } catch (\Exception $e) { $transaction->rollBack(); throw $e; }
十二、rest風格API獲取客戶端提交的get和post的數組
// post Yii::$app->request->bodyParams // get Yii::$app->request->queryParams;
1三、一個控制器調用其餘控制器action的方法:
方法一:
是經典的重寫actions方法
public function actions() { return [ 'error' => [ 'class' => 'yii\web\ErrorAction', ], 'captcha' => [ 'class' => 'yii\captcha\CaptchaAction', 'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null, ], ]; }
actions繼承yii\base\Actions類,並重寫父類的run方法。
方法二:
site控制器以下,訪問MemberController控制器下面的index方法。
class SiteController extends Controller { public function actionIndex(){ Yii::$app->runAction('member/index', ['param'=>'123']); } }
MemberController控制器以下:
class MemberController extends Controller { public function actionIndex($param = '456'){ echo "second Controller".$param; } }
訪問:http://www.yii.dev/site/index.html
輸出:second Controller123
1四、點擊下載,以下載安卓APK文件。
public function actionDownload(){ return \Yii::$app->response->setDownloadHeaders("http://xxx.com/apk/com.trade.activity.3.0.8.apk"); //return \Yii::$app->response->sendFile("./com.trade.activity.3.0.8.apk"); }
1五、YII模塊IP白名單設置,增長安全性
$config['modules']['gii'] = [ 'class' => 'yii\gii\Module', 'allowedIPs' => ['127.0.0.1', '::1','10.10.1.*'], ];
$config['modules']['debug'] = [ 'class' => 'yii\debug\Module', 'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*', '192.168.33.1'], ];
1六、防止 SQL 和 Script 注入
use yii\helpers\Html; use yii\helpers\HtmlPurifier; echo Html::encode($view_hello_str) //能夠原樣顯示<script></script>代碼 echo HtmlPurifier::process($view_hello_str) //能夠過濾掉<script></script>代碼
1七、驗證某個ID值是否存在
//以前一直用$model->findOne($id);exists()方法,資源節約,有沒有?!
public function validateAttribute($model, $attribute) { $value = $model->$attribute; if (!Status::find()->where(['id' => $value])->exists()) { $model->addError($attribute, $this->message); } }
1八、批量查詢
如查詢並循環10000條數據。一次性拿1萬條內存會有壓力,經過批量查詢,每次拿1000條,那麼內存始終只有1000條的佔有量。
foreach(Member::find()->batch(1000) as $value){ //do something //print_r(count($value)); }
1九、關於CSRF驗證
方法一:關閉Csrf,除非必要,不然不推薦
public function init(){ $this->enableCsrfValidation = false; }
方法二:普通提交,form表單中加入隱藏域
<input name="_csrf" type="hidden" id="_csrf" value="<?= Yii::$app->request->csrfToken ?>">
方法三:ajax異步提交,加入_csrf字段
var csrfToken = $('meta[name="csrf-token"]').attr("content"); $.ajax({ type: 'POST', url: url, data: {_csrf:csrfToken}, success: success, dataType: dataType });
20、YII命令行生成數據庫文件
自動列出可用的migrate文件
php yii migrate
從vendor/callmez/wechat/migrations目錄下生成數據表
php yii migrate --migrationPath=@callmez/wechat/migrations
從當前應用/migrations/db1下初始化數據到db1表
php yii migrate --migrationPath=@app/migrations/db1 --db=db1
21.關聯查詢
//客戶表Model:CustomerModel //訂單表Model:OrdersModel //國家表Model:CountrysModel //首先要創建表與表之間的關係 //在CustomerModel中添加與訂單的關係 Class CustomerModel extends \yii\db\ActiveRecord { ... public function getOrders() { //客戶和訂單是一對多的關係因此用hasMany //此處OrdersModel在CustomerModel頂部別忘了加對應的命名空間 //id對應的是OrdersModel的id字段,order_id對應CustomerModel的order_id字段 return $this->hasMany(OrdersModel::className(), ['id'=>'order_id']); } public function getCountry() { //客戶和國家是一對一的關係因此用hasOne return $this->hasOne(CountrysModel::className(), ['id'=>'Country_id']); } .... } // 查詢客戶與他們的訂單和國家 CustomerModel::find()->with('orders', 'country')->all(); // 查詢客戶與他們的訂單和訂單的發貨地址 CustomerModel::find()->with('orders.address')->all(); // 查詢客戶與他們的國家和狀態爲1的訂單 CustomerModel::find()->with([ 'orders' => function ($query) { $query->andWhere('status = 1'); }, 'country', ])->all();
2二、yii2中關閉debug後return $this->redirect($url);不能跳轉,服務器報500錯誤。
問題分析:
1.必須 return 才能讓$this->redirect($url);立馬跳轉, 而不執行後續代碼;
2.redirect() 中指定了響應的 http status code,默認是302;
3.當執行$this->redirect($url)時,不論是否在後面加return false 、return true都沒有用,仍是繼續執行完代碼。使用header("Location:$url");exit;能夠解決此問題,可是,這不是yii2的邏輯,並不完美。
解決辦法:
【本文由php_sir的博客 http://blog.sina.com.cn/phpsir原創,未經受權禁止轉載】
1.在正常狀況下,使用 return $this->redirect($url);
2.在解決方案1不生效時,用$this->redirect($url);Yii::$app->response->send();
3.在解決方案2不生效時,用$this->redirect($url);Yii::$app->end();
總結:
用Yii::$app->end();、Yii::$app->response->send();無論在actionXXX仍是init方法都能終止代碼,而return只能在action終止代碼,是由於在init()裏僅僅是代碼的執行,return只是代碼返回。