首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

Yii 1.x 開發技巧大全:性能優化、安全、調試與實戰經驗總結

     編輯:PHP 綜合知識

前言

Yii 1.x 作為經典高性能 PHP 框架,雖已進入維護模式,但大量存量專案仍在運行。本文匯總開發實戰中高頻技巧,涵蓋配置優化、ActiveRecord 進階、緩存策略、安全加固、調試工具、部署運維等核心場景。

一、配置與性能優化

1.1 數據庫 Schema 緩存

// main.php components.db
'db' => [
    'class' => 'CDbConnection',
    'connectionString' => 'mysql:host=localhost;dbname=test',
    'username' => 'root',
    'password' => '',
    'charset' => 'utf8',
    'schemaCachingDuration' => 3600, // 關鍵:緩存表結構 1 小時
    'schemaCacheID' => 'cache',      // 需配置 cache 組件
],

前提:必須配置 cache 組件(如 CFileCache/CMemCache/CRedisCache),否則 schemaCachingDuration 不生效。

1.2 SQL 執行分析與性能分析

// main.php log 組件 routes 添加
'routes' => [
    // 網頁底部顯示 SQL 日志
    ['class' => 'CWebLogRoute', 'levels' => 'trace,info,error,warning', 'categories' => 'system.db.*'],
    // FirePHP 輸出到瀏覽器控制台(需安裝插件)
    ['class' => 'CWebLogRoute', 'levels' => 'trace,info,error,warning', 'categories' => 'system.db.*', 'showInFireBug' => true],
    // 代碼塊執行時間分析
    ['class' => 'CProfileLogRoute', 'levels' => 'error, warning'],
],

代碼中埋點:

Yii::beginProfile('blockID');
// 待測代碼段
Yii::endProfile('blockID');

// 獲取統計:執行語句數、總耗時
$stats = Yii::app()->db->getStats(); // [sqlCount, sqlTime]

1.3 參數綁定日志

'db' => [
    'enableParamLogging' => true, // 日志中顯示綁定參數值
],

1.4 日志持久化到數據庫

'routes' => [
    ['class' => 'CDbLogRoute', 'logTableName' => 'applog', 'connectionID' => 'db'],
],

表 applog 會自動創建,若失敗請參考 API 手動建表。

1.5 請求級調試開關

// index.php 入口文件
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL', 10); // 堆疊深度

二、ActiveRecord 進階用法

2.1 關聯查詢優化:together 與 joinType

$criteria = new CDbCriteria();
$criteria->with = [
    'author' => ['together' => true], // 強制單條 SQL(含 LIMIT 時)
    'categories' => ['joinType' => 'INNER JOIN'], // 改變 JOIN 類型
];
$posts = Post::model()->findAll($criteria);
  • together=true:主表有 LIMIT/OFFSET 時仍生成單條 SQL,避免分頁記錄數不準
  • 多對多查詢分頁記錄重複問題:$criteria->group = true 或 $criteria->distinct = true

2.2 非主鍵關聯

// 關聯定義
'user' => [self::BELONGS_TO, 'User', '', 'on' => 'name=userName', 'select' => 'TrueName'],

// 表名帶前綴的多對多
'categories' => [self::MANY_MANY, 'Category', '{{post_category}}(post_id,category_id)']

2.3 作用域與鏈式查詢

// Model 中定義
public function scopes() {
    return [
        'published' => ['condition' => 'status=1'],
        'recent'    => ['order' => 'create_time DESC', 'limit' => 10],
    ];
}
// 使用
Post::model()->published()->recent()->findAll();

2.4 批量操作與原生 SQL

// 批量插入(需自構建 SQL)
$command = Yii::app()->db->createCommand();
$command->insert('post', ['title' => 'A', 'content' => '...']);
// 或使用 DAO 批量
Yii::app()->db->createCommand()->execute("INSERT INTO post (title) VALUES ('A'),('B'),('C')");

// 刪除條件匹配
Post::model()->deleteAllByAttributes(['status' => 0]);

三、緩存策略

3.1 片段緩存

if ($this->beginCache('widget-sidebar', ['duration' => 3600, 'dependency' => $dependency])) {
    // 昂貴渲染邏輯
    $this->widget('RecentPostsWidget');
    $this->endCache();
}

3.2 頁面緩存(動作過濾器)

public function filters() {
    return [
        ['COutputCache + index,list', 'duration' => 300, 'varyByParam' => ['page']],
    ];
}

3.3 動態內容(緩存中嵌入實時數據)

$this->renderDynamic('$this->renderPartial("_user_panel", [], true)');

3.4 多站點/子域名緩存隔離

'varyByExpression' => 'Yii::app()->request->hostInfo',

四、安全加固

4.1 CSRF 防護

'request' => ['enableCsrfValidation' => true],

表單必須使用 CHtml::form() 自動輸出隱藏 token 欄位。

4.2 Cookie 驗證

'request' => ['enableCookieValidation' => true],

操作 Cookie 使用 CHttpCookie 類,自動簽名驗證。

4.3 XSS 防護:CHtmlPurifier

$purifier = new CHtmlPurifier();
$purifier->options = ['HTML.Allowed' => 'p,b,strong,i,em,u,a[href],ul,ol,li'];
$clean = $purifier->purify($dirty_html);

// 或在視圖中
$this->beginWidget('CHtmlPurifier');
echo $user_content;
$this->endWidget();

4.4 防止重複提交

// Controller
if ($model->save()) {
    Yii::app()->user->setFlash('success', '保存成功');
    $this->refresh(); // PRG 模式
}
// View
if (Yii::app()->user->hasFlash('success')) {
    echo '
' . Yii::app()->user->getFlash('success') . '
'; }

五、URL 管理與路由

5.1 路由規則進階

'urlManager' => [
    'urlFormat' => 'path',
    'showScriptName' => false,
    'rules' => [
        'post/' => 'post/view',
        'post/' => 'post/view', // 非數字標識
        'category/' => ['post/index', 'caseSensitive' => false],
        // matchValue=true 要求參數值也匹配正則
        'archive//' => ['post/archive', 'matchValue' => true],
    ],
],

5.2 反向生成 URL

$url = $this->createUrl('post/view', ['id' => 123]); // /post/123
$url = Yii::app()->createAbsoluteUrl('post/view', ['id' => 123]); // 完整域名

六、國際化與多語言

'sourceLanguage' => 'en_us',
'language' => 'zh_cn', // 視圖自動尋找 views/zh_cn/
// 訊息翻譯
Yii::t('app', 'Hello {name}', ['{name}' => 'World']);
// 日期/數字格式化
Yii::app()->dateFormatter->format('yyyy-MM-dd', time());
Yii::app()->numberFormatter->format('#,##0.00', 12345.6);

七、部署與運維

7.1 維護模式

'catchAllRequest' => ['site/maintenance'], // 所有請求導向維護頁

7.2 多域名 Session 共享

'session' => [
    'cookieParams' => ['domain' => '.example.com', 'lifetime' => 0],
    'timeout' => 3600,
],

7.3 資源發布優化

'assetManager' => [
    'linkAssets' => true, // 生產環境使用符號鏈接而非複製
    'excludeFiles' => ['.svn', '.gitignore'],
],

7.4 錯誤處理頁面

'errorHandler' => ['errorAction' => 'site/error'],
// SiteController::actionError()
public function actionError() {
    $error = Yii::app()->errorHandler->error;
    if (Yii::app()->request->isAjaxRequest) echo $error['message'];
    else $this->render('error', $error);
}

八、常用組件速查

組件/類用途關鍵方法
CActiveForm表單構建+AJAX 驗證validate(), enableAjaxValidation
CGridView後台數據表格columns, filter, dataProvider
CListView列表分頁顯示itemView, template, sortableAttributes
CDetailView詳情頁只讀顯示attributes
CBreadcrumbs麵包屑導航links, homeLink, separator
CAutoComplete自動完成輸入框url, multiple, htmlOptions
CCaptcha驗證碼captchaAction, showRefreshButton
CMarkdownMarkdown 渲染purifyOutput
CClipWidget內容片段捕獲復用id, renderClip
CStatePersister跨請求狀態持久化文件/數據庫存儲

九、調試技巧匯總

  1. SQL 調試:Yii::log($sql, 'trace', 'system.db.CDbCommand') 或開啟 CWebLogRoute
  2. 變量檢查:Yii::trace(CVarDumper::dumpAsString($var), 'my.category')
  3. 終止輸出日志:Yii::app()->end() 觸發 onEndRequest 確保日志寫入(勿用 die/exit)
  4. FirePHP:安裝瀏覽器插件,配置 showInFireBug=true 非侵入式調試
  5. 性能分析:Yii::beginProfile/endProfile + CProfileLogRoute

十、避坑指南精選

  • renderPartial 第 4 參數:$this->renderPartial('view', [], false, true) 才會輸出客戶端腳本(JS/CSS 註冊)
  • addInCondition 空數組自動處理為 0=1,無需額外判斷
  • CActiveRecord::exists():快速判斷記錄是否存在(主鍵/條件)
  • 關聯 with() 返回 CActiveFinder,調用 together() 強制單 SQL
  • 佈署模式 YII_DEBUG=false 時錯誤頁面不顯示堆疊,需配置 errorHandler
  • 模型驗證規則 array('attr1, attr2', 'required') 共用消息時需注意屬性佔位符 {attribute}
  • ctype_* 函數族(ctype_digit 等)比正則更高效驗證純數字/字母
  • CController::setPageState() 保存頁面狀態(跨請求表單數據)
  • 行為類綁定:behaviors() 返回 ['BehaviorName' => 'path.to.Class']
  • 模塊路徑別名:Yii::getPathOfAlias('moduleId') 獲取模塊基礎路徑

總結

Yii 1.x 憑藉組件化架構、ActiveRecord、緩存抽象、安全過濾器等特性,仍是中型專案的可靠選擇。核心建議:

  1. 生產環境務必開啟 Schema 緩存、頁面/片段緩存、CSRF/Cookie 驗證
  2. 善用 CDbCriteria、with/together、scopes 優化數據庫交互
  3. 建立統一日志、錯誤處理、部署流程(catchAllRequest 維護模式)
  4. 遷移 Yii 2.x 時關注:命名空間、依賴注入、ActiveRecord 查詢介面變更、組件重命名
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved