YII讀書筆記
=========================================================================================================================
模型-檢視-控制器 (MVC)
一個典型的工作流
-
使用者發出了訪問 URL
http://www.example.com/index.php?r=post/show&id=1
的請求, Web 伺服器通過執行入口指令碼index.php
處理此請求。 - 入口指令碼建立了一個 應用 例項並執行。
-
應用從一個叫做
request
的 應用元件 中獲得了使用者請求的詳細資訊。 -
應用在一個名叫
urlManager
的應用元件的幫助下,決定請求的 控制器 和 動作 。在這個例子中,控制器是post
,它代表PostController
類; 動作是show
,其實際含義由控制器決定。 -
應用建立了一個所請求控制器的例項以進一步處理使用者請求。控制器決定了動作
show
指向控制器類中的一個名為actionShow
的方法。然後它建立並持行了與動作關聯的過濾器(例如訪問控制,基準測試)。 如果過濾器允許,動作將被執行。 -
動作從資料庫中讀取一個 ID 為
1
的Post
模型。 -
動作通過
Post
模型渲染一個名為show
的 檢視。 -
檢視讀取並顯示
Post
模型的屬性。 - 檢視執行一些 小物件。
- 檢視的渲染結果被插入一個 佈局。
- 動作完成檢視渲染並將其呈現給使用者。
入口指令碼
入口指令碼是處理使用者的初始引導PHP指令碼。它是唯一一個終端使用者可直接請求執行的PHP指令碼
// 在生產環境中請刪除此行defined('YII_DEBUG') or define('YII_DEBUG',true); // 包含Yii引導檔案require_once('path/to/yii/framework/yii.php'); // 建立一個應用例項並執行$configFile='path/to/config/file.php'; Yii::createWebApplication($configFile)->run();
yii.php
。然後他按指定的配置建立了一個Web
應用例項並執行。除錯模式
yii.php
檔案之前定義此常量YII_DEBUG
為true應用
前端控制器
。應用配置
配置是一個鍵值對陣列。每個鍵和應用例項屬性一一對應,每個值即相應屬性的初始值。 例如,如下的配置設定了CWebApplication應用的name 和 defaultController 屬性的值。
array( 'name'=>'Yii Framework', 'defaultController'=>'site', )
protected/config/main.php
)中儲存這些配置$app=Yii::createWebApplication($webApplication,$configFile);
應用基礎目錄
protected
的子目錄
可以通過在基礎目錄中放置一個.htaccess
檔案很簡單的實現。 .htaccess
內容如下:
deny from all
應用元件
通過配置config/main.php的 components 屬性, 我們可以自定義應用中用到的任何元件類及其屬性值。例如,我們可以配置應用的CMemCache 元件, 這樣它就可以使用多個 memcache 伺服器實現快取:
array( 'components'=>array( 'cache'=>array( 'class'=>'CMemCache', 'servers'=>array( array('host'=>'server1', 'port'=>11211, 'weight'=>60), array('host'=>'server2', 'port'=>11211, 'weight'=>40), ), ), ), )
Yii::app()->ComponentID
,其中的 ComponentID
是指元件的ID(例如Yii::app()->db
)核心應用元件
-
assetManager: CAssetManager - 管理私有資原始檔的釋出。
-
authManager: CAuthManager - 管理基於角色的訪問控制 (RBAC).
-
cache: CCache - 提供資料快取功能。注意,你必須指定實際的類(例如CMemCache, CDbCache)。 否則,當你訪問此元件時將返回 NULL。
-
clientScript: CClientScript - 管理客戶端指令碼 (javascripts 和 CSS).
-
coreMessages: CPhpMessageSource - 提供 Yii 框架用到的核心資訊的翻譯。
-
db: CDbConnection - 提供資料庫連線。注意,使用此元件你必須配置其 connectionString 屬性。
-
errorHandler: CErrorHandler - 處理未捕獲的 PHP 錯誤和異常。
-
format: CFormatter - 格式化數值顯示。此功能從版本 1.1.0 起開始提供。
-
messages: CPhpMessageSource - 提供Yii應用中使用的資訊翻譯。
-
request: CHttpRequest - 提供關於使用者請求的資訊。
-
securityManager: CSecurityManager - 提供安全相關的服務,例如雜湊,加密。
-
session: CHttpSession - 提供session相關的功能。
-
statePersister: CStatePersister - 提供全域性狀態持久方法。
-
urlManager: CUrlManager - 提供 URL 解析和建立相關功能
-
themeManager: CThemeManager - 管理主題。
應用的生命週期
當處理使用者請求時,應用將經歷如下宣告週期:
-
通過 CApplication::preinit() 預初始化應用;
-
設定類的自動裝載器和錯誤處理 ;
-
註冊核心類元件;
-
載入應用配置; (main.php 對應2,3,4步驟)
-
通過 CApplication::init() 初始化應用:
- 註冊應用行為;
- 載入靜態應用元件;
-
觸發 onBeginRequest 事件;
-
處理使用者請求: (對應acitonCotroller)
- 解析使用者請求;
- 建立控制器;
- 執行控制器;
-
觸發 onEndRequest 事件。
控制器
動作
的最簡形式,就是一個名字以 action
開頭的控制器類方法。路由
控制器和動作以 ID 識別。控制器 ID 是一種 'path/to/xyz' 的格式,對應相應的控制器類檔案protected/controllers/path/to/XyzController.php
,
其中的標誌 xyz
應被替換為實際的名字
(例如 post
對應 protected/controllers/PostController.php
).
動作 ID 是除去 action
字首的動作方法名。例如,如果一個控制器類含有一個名為 actionEdit
的方法,則相應的動作
ID 為 edit
post/edit
代表 PostController
及其 edit
動作。預設情況下,URL http://hostname/index.php?r=post/edit
即請求此控制器和動作控制器例項化
'path/to/xyz'
的格式,控制器類的名字將判斷為 XyzController
,
相應的類檔案則為protected/controllers/path/to/XyzController.php
。admin/user
將被解析為控制器類 UserController
,類檔案是 protected/controllers/admin/UserController.php
。
如果類檔案不存在,將觸發一個 404 CHttpException 異常動作
action
單詞作為字首命名的方法。定義一個新動作類,可用如下程式碼:
class UpdateAction extends CAction{ public function run() { // place the action logic here }}
為了讓控制器注意到這個動作,我們要用如下方式覆蓋控制器類的actions() 方法:
class PostController extends CController{ public function actions() { return array( 'edit'=>'application.controllers.post.UpdateAction', ); }}
application.controllers.post.UpdateAction
指定動作類檔案為protected/controllers/post/UpdateAction.php
.通過編寫基於類的動作,我們可以將應用組織為模組的風格。例如, 如下目錄結構可用於組織控制器相關程式碼:
protected/ controllers/ PostController.php UserController.php post/ CreateAction.php ReadAction.php UpdateAction.php user/ CreateAction.php ListAction.php ProfileAction.php UpdateAction.php
動作引數繫結
$_GET
填充。
1.1.4之前,使用動作引數功能:從 $_GET
中提取引數時:
class PostController extends CController{ public function actionCreate() { if(isset($_GET['category'])) $category=(int)$_GET['category']; else throw new CHttpException(404,'invalid request'); if(isset($_GET['language'])) $language=$_GET['language']; else $language='en'; // ... fun code starts here ... }}
1.1.4開始,使用動作引數功能:
class PostController extends CController{ public function actionCreate($category, $language='en') { $category=(int)$category; // ... fun code starts here ... }}
class PostController extends CController{ public function actionCreate(array $categories) //引數強制轉換為array型別 { // Yii will make sure $categories be an array }}
過濾器
過濾器可以定義為一個控制器類的方法。方法名必須以 filter
開頭。例如,現有的 filterAccessControl
方法定義了一個名為 accessControl
的過濾器。
過濾器方法必須為如下結構:
public function filterAccessControl($filterChain){ // 呼叫 $filterChain->run() 以繼續後續過濾器與動作的執行。}
$filterChain->run()
以繼續執行後續過濾器和動作。過濾器也可以是一個 CFilter 或其子類的例項。如下程式碼定義了一個新的過濾器類:
class PerformanceFilter extends CFilter{ protected function preFilter($filterChain) { // 動作被執行之前應用的邏輯 return true; // 如果動作不應被執行,此處返回 false } protected function postFilter($filterChain) { // 動作執行之後應用的邏輯 }}
要對動作應用過濾器,我們需要覆蓋 CController::filters()
方法。此方法應返回一個過濾器配置陣列。例如:
class PostController extends CController{ ...... public function filters() { return array( 'postOnly + edit, create'), array( 'application.filters.PerformanceFilter - edit, create', 'unit'=>'second', ), ); } }
上述程式碼指定了兩個過濾器: postOnly
和 PerformanceFilter
。 postOnly
過濾器是基於方法的(相應的過濾器方法已在 CController 中定義);
而 performanceFilter
過濾器是基於物件的。路徑別名application.filters.PerformanceFilter
指定過濾器類檔案是protected/filters/PerformanceFilter
。我們使用一個陣列配置 PerformanceFilter
,這樣它就可被用於初始化過濾器物件的屬性值。此處 PerformanceFilter
的 unit
屬性值將被初始為 second
。
使用加減號,我們可指定哪些動作應該或不應該應用過濾器。上述程式碼中, postOnly
應只被應用於 edit
和 create
動作,而 PerformanceFilter
應被應用於
除了 edit
和 create
之外的動作。
如果過濾器配置中沒有使用加減號,則此過濾器將被應用於所有動作。
模型
2>Active Record (AR) 是一種用於通過物件導向的風格抽象化資料庫訪問的設計模式。 每個 AR 物件是一個 CActiveRecord 或其子類的例項。 資料物件的每個欄位代表資料表中的一行。 行中的欄位對應 AR 物件中的屬性。更多關於 AR 的細節請閱讀 Active Record.
檢視
edit
的名稱出自一個名為 edit.php
的指令碼檔案.要渲染時如,需通過傳遞檢視的名稱呼叫 CController::render()。這個方法將在 protected/views/ControllerID
目錄下尋找對應的檢視檔案.如controller路徑為:\protected\controllers\contract\applyController.php
對應 檢視目錄:protected\views\contract\apply\$this
來訪問當前控制器例項
用以下 推送
的方式傳遞資料到檢視裡:
$this->render('edit', array( 'varName1'=>$value1, 'varName2'=>$value2, ));
佈局
$content
則儲存了內容檢視的渲染結果.protected/views/layouts/main.php
是預設的佈局檔案.這可以通過改變 CWebApplication::layout 或者 CWebApplication::layout 進行自定義。小物件
按如下檢視指令碼來使用一個小物件:
<?php $this->beginWidget('path.to.WidgetClass'); ?> ...可能會由小物件獲取的內容主體... <?php $this->endWidget(); ?>
或者
<?php $this->widget('path.to.WidgetClass'); ?>
後者用於不需要任何 body 內容的元件.
小物件可通過配置來定製它的表現.這是通過呼叫 CBaseController::beginWidget 或 CBaseController::widget 設定其初始化屬性值來完成的.例如,當使用 CMaskedTextField 小物件時,我們想指定被使用的 mask (可理解為一種輸出格式,譯者注).我們通過傳遞一個攜帶這些屬性初始化值的陣列來實現.這裡的陣列的鍵是屬性的名稱,而陣列的值則是小物件屬性所對應的值.正如以下所示 :
<?php$this->widget('CMaskedTextField',array( 'mask'=>'99/99/9999')); ?>
繼承 CWidget 並覆蓋其init() 和 run() 方法,可以定義一個新的小物件:
class MyWidget extends CWidget{ public function init() { // 此方法會被 CController::beginWidget() 呼叫 } public function run() { // 此方法會被 CController::endWidget() 呼叫 }}
小物件可以像一個控制器一樣擁有它自己的檢視.預設情況下,小物件的檢視檔案位於包含了小物件類檔案目錄的 views
子目錄之下.這些檢視可以通過呼叫 CWidget::render() 渲染,這一點和控制器很相似.唯一不同的是,小物件的檢視沒有佈局檔案支援。另外,小物件檢視中的$this
指向小物件例項而不是控制器例項。
系統檢視
framework/views
下,
Yii 提供了一系列預設的系統檢視. 他們可以通過在 protected/views/system
下建立同名檢視檔案進行自定義元件
元件屬性
元件的屬性就像物件的公共成員變數。它是可讀寫的。例如:
$width=$component->textWidth; // 獲取 textWidth 屬性$component->enableCaching=true; // 設定 enableCaching 屬性
定義一個元件屬性: 只需在元件類中定義一個公共成員變數即可。更靈活的方式是定義其 getter 和 setter 方法,例如:
public function getTextWidth(){ return $this->_textWidth; } public function setTextWidth($value){ $this->_textWidth=$value; }
textWidth
(名字是大小寫不敏感的)。
當讀取屬性時,getTextWidth()
就會被呼叫,其返回值則成為屬性值;相似的,
當寫入屬性時,setTextWidth()
被呼叫。如果
setter 方法沒有定義,則屬性將是隻讀的, 如果對其寫入則會丟擲一個異常。使用 getter 和 setter 方法定義一個屬性有一個好處:即當讀取或寫入屬性時, 可以執行額外的邏輯(例如,執行驗證,觸發事件)。元件事件
元件事件是一些特殊的屬性,它們使用一些稱作 事件控制程式碼
(event handlers)
的方法作為其值。 分配一個方法到一個事件將會引起方法在事件被喚起處自動被呼叫。因此, 一個元件的行為可能會被一種在部件開發過程中不可預見的方式修改。
元件事件以 on
開頭的命名方式定義。和屬性通過
getter/setter 方法來定義的命名方式一樣, 事件的名稱是大小寫不敏感的。以下程式碼定義了一個 onClicked
事件:
public function onClicked($event){ $this->raiseEvent('onClicked', $event); }
這裡作為事件引數的 $event
是 CEvent 或其子類的例項。
我們可以附加一個方法到此 event,如下所示:
$component->onClicked=$callback;
這裡的 $callback
指向了一個有效的
PHP 回撥。它可以是一個全域性函式也可以是類中的一個方法。 如果是後者,它必須以一個陣列的方式提供: array($object,'methodName')
.
事件控制程式碼的結構如下:
function methodName($event){ ...... }
這裡的 $event
即描述事件的引數(它來源於 raiseEvent()
呼叫)。$event
引數是 CEvent 或其子類的例項。
至少,它包含了關於誰觸發了此事件的資訊。
從版本 1.0.10 開始,事件控制程式碼也可以是一個PHP 5.3以後支援的匿名函式。例如,
$component->onClicked=function($event) { ...... }
如果我們現在呼叫 onClicked()
,onClicked
事件將被觸發(在 onClicked()
中),
附屬的事件控制程式碼將被自動呼叫。
一個事件可以繫結多個控制程式碼。當事件觸發時, 這些控制程式碼將被按照它們繫結到事件時的順序依次執行。如果控制程式碼決定組織後續控制程式碼被執行,它可以設定 $event->handled 為 true
元件行為
繼承(inherited)
,
而不是專有化繼承(即普通的類繼承).要使用一個行為,它必須首先通過呼叫此行為的 attach() 方法繫結到一個元件。然後我們就可以通過元件呼叫此行為方法:
// $name 在元件中實現了對行為的唯一識別$component->attachBehavior($name,$behavior); // test() 是行為中的方法。$component->test();
已繫結的行為可以像一個元件中的普通屬性一樣訪問。 例如,如果一個名為 tree
的行為繫結到了一個元件,我們就可以通過如下程式碼獲得指向此行為的引用。
$behavior=$component->tree; // 等於下行程式碼:// $behavior=$component->asa('tree');
行為是可以被臨時禁止的,此時它的方法開就會在元件中失效.例如:
$component->disableBehavior($name); // 下面的程式碼將丟擲一個異常$component->test(); $component->enableBehavior($name); // 現在就可以使用了$component->test();
兩個同名行為繫結到同一個元件下是有可能的.在這種情況下,先繫結的行為則擁有優先權.
當和 events, 一起使用時,行為會更加強大. 當行為被繫結到元件時,行為裡的一些方法就可以繫結到元件的一些事件上了. 這樣一來,行為就有機觀察或者改變元件的常規執行流程.
自版本 1.1.0 開始,一個行為的屬性也可以通過繫結到的元件來訪問。 這些屬性包含公共成員變數以及通過 getters 和/或 setters 方式設定的屬性。 例如, 若一個行為有一個 xyz 的屬性,此行為被繫結到元件 $a,然後我們可以使用表示式 $a->xyz
訪問此行為的屬性。
模組
建立模組
模組組織在一個目錄中,目錄的名字即模組的唯一 ID
模組的典型的目錄結構:
forum/ ForumModule.php 模組類檔案 components/ 包含可複用的使用者元件 views/ 包含小物件的檢視檔案 controllers/ 包含控制器類檔案 DefaultController.php 預設的控制器類檔案 extensions/ 包含第三方擴充套件 models/ 包含模組類檔案 views/ 包含控制器檢視和佈局檔案 layouts/ 包含佈局檔案 default/ 包含 DefaultController 的檢視檔案 index.php 首頁檢視檔案
路徑別名與名字空間
system.web.CController
會被翻譯為yii/framework/web/CController
Root Alias
system.web.CController
會被翻譯為yii/framework/web/CController
Importing Classes
使用別名可以很方便的匯入類的定義。 例如,如果我們想包含 CController 類的定義,我們可以呼叫如下程式碼
Yii::import('system.web.CController');
include
和 require
不同,它更加高效。
匯入(import)的類定義並不會真正被包含進來,直到它第一次被引用。 多次匯入同樣的名字空間也會比 include_once
和 require_once
快得多使用Class Map
使用Class Map
若要使用預匯入功能,要在CWebApplication::run()執行前執行下面的程式碼:
Yii::$classMap=array( 'ClassName1' => 'path/to/ClassName1.php', 'ClassName2' => 'path/to/ClassName2.php', ...... );
匯入目錄
使用如下語法匯入整個目錄,這樣此目錄下的類檔案就會在需要時被自動包含。
Yii::import('system.web.*');
Namespace
使用名稱空間的類
application\components\GoogleMap
所對應的路徑必須和別名:application.components.GoogleMap
一致。開發規範
Yii 程式設計中推薦的開發規範。 為簡單起見,我們假設 WebRoot
是
Yii 應用安裝的目錄。
URL
預設情況下,Yii 識別如下格式的 URL:
http://hostname/index.php?r=ControllerID/ActionID
1.r
GET
變數意為 路由(route) ,它可以被Yii解析為
控制器和動作。 ActionID
被省略,控制器將使用預設的動作(在CController::defaultAction中定義); http://hostname/ControllerID/ActionID.html
程式碼
1.命名變數、函式和類時使用 駝峰風格,即每個單詞的首字母大寫並連在一起,中間無空格。 變數名和函式名應該使它們的第一個單詞全部小寫,以使其區別於類名(例如:$basePath
, runController()
, LinkPager
)。對私有類成員變數來說,我們推薦以下劃線作為其名字字首(例如: $_actionList
)
Controller
結尾。那麼控制器
ID 即類名的首字母小寫並去掉單詞Controller
。
例如,PageController
類的
ID 就是 page
配置
array('name'=>'My
application', 'basePath'=>'./protected')
初始化了 name
和 basePath
屬性為它們相應的陣列值檔案
命名和使用檔案的規範取決於它們的型別。
index
檢視位於 index.php
檔案中。
檢視檔案是一個PHP指令碼檔案,它包含了用於呈現內容的 HTML和PHP程式碼目錄
-
WebRoot/protected
: 這是 應用基礎目錄, 是放置所有安全敏感的PHP指令碼和資料檔案的地方。Yii 有一個預設的application
別名指向此目錄。 此目錄及目錄中的檔案應該保護起來防止Web使用者訪問。它可以通過CWebApplication::basePath 自定義。 -
WebRoot/protected/runtime
: 此目錄放置應用在執行時產生的私有臨時檔案。 此目錄必須對 Web 伺服器程式可寫。它可以通過 CApplication::runtimePath自定義。 -
WebRoot/protected/extensions
: 此目錄放置所有第三方擴充套件。 它可以通過 CApplication::extensionPath 自定義。 -
WebRoot/protected/modules
: 此目錄放置所有的應用 模組,每個模組使用一個子目錄。 -
WebRoot/protected/controllers
: 此目錄放置所有控制器類檔案。 它可以通過CWebApplication::controllerPath 自定義。 -
WebRoot/protected/views
: 此目錄放置所有試圖檔案, 包含控制器檢視,佈局檢視和系統檢視。 它可以通過CWebApplication::viewPath 自定義。 -
WebRoot/protected/views/ControllerID
: 此目錄放置單個控制器類中使用的所有檢視檔案。 此處的ControllerID
是指控制器的 ID 。它可以通過 CController::viewPath 自定義。 -
WebRoot/protected/views/layouts
: 此目錄放置所有佈局檢視檔案。它可以通過CWebApplication::layoutPath 自定義。 -
WebRoot/protected/views/system
: 此目錄放置所有系統檢視檔案。 系統檢視檔案是用於顯示異常和錯誤的模板。它可以通過 CWebApplication::systemViewPath 自定義。 -
WebRoot/assets
: 此目錄放置公共資原始檔。 資原始檔是可以被髮布的,可由Web使用者訪問的私有檔案。此目錄必須對 Web 伺服器程式可寫。 它可以通過 CAssetManager::basePath 自定義 -
WebRoot/themes
: 此目錄放置應用使用的不同的主題。每個子目錄即一個主題,主題的名字即目錄的名字。 它可以通過 CThemeManager::basePath 自定義。
資料庫
多數Web 應用是由資料庫驅動的。 推薦在對錶和列命名時使用如下命名規範。
-
資料庫表名和列名都使用小寫命名。
-
名字中的單詞應使用下劃線分割 (例如
product_order
)。 -
對於表名,推薦使用單數名字。
-
表名可以使用一個通用字首,例如
tbl_
。這樣當應用所使用的表和另一個應用說使用的表共存於同一個資料庫中時就特別有用。 這兩個應用的表可以通過使用不同的表字首很容易地區別開。
開發流程
-
建立目錄結構骨架。
-
配置此 應用。通過修改應用配置檔案實現的。 此步驟可能也需要編寫一些應用元件(例如使用者元件)。
-
為每個型別的資料(表)建立一個 模型 類。
Gii
工具可以用於快速為每個資料表建立 active record 類為每個型別的使用者請求 建立一個 控制器 類。 具體如何對使用者請求歸類要看實際需求。總體來說,如果一個模型類需要被使用者訪問,就應該有一個相應的控制器類。Gii
工具也可以自動實現這一步驟。 -
在控制器類中配置必要的動作 過濾器。
-
如果需要主題功能,建立 主題 。
-
如果需要 國際化(I18N) ,建立翻譯資訊。
-
對可快取的資料點和檢視點應用適當的 快取 技術。
-
最終 調整 與部署。
上述的每個步驟中,可能需要建立並執行測試用例。
通過HTML表單收集使用者資料是Web程式開發的主要工作之一。除了表單設計外, 開發者還需要將現存的或預設的資料填充到表單,驗證使用者輸入, 對無效的輸入顯示適當的錯誤資訊,儲存輸入到永續性儲存器。通過其 MVC 結構極大地簡化了此工作流程。
處理表單時,通常需要以下步驟:
- 建立用於表現所要收集資料欄位的模型類。
- 建立一個控制器動作,響應表單提交。
- 在檢視指令碼中建立與控制器動作相關的表單。
建立模型
定義模型類
建立了一個 LoginForm
模型類用於在一個登入頁中收集使用者的輸入。
由於登錄資訊只被用於驗證使用者,並不需要儲存,因此我們將 LoginForm
建立為一個
表單模型。
class LoginForm extends CFormModel{ public $username; public $password; public $rememberMe=false; }
LoginForm
中定義了三個屬性: $username
, $password
和 $rememberMe
。用於儲存使用者輸入的使用者名稱和密碼,還有使用者是否想記住他的登入的選項。
由於 $rememberMe
有一個預設的值 false
,相應的選項在初始化顯示在登入表單中時將是未勾選狀態。
宣告驗證規則
rules()
方法中指定這些驗證規則,
此方法應返回一個規則配置陣列。class LoginForm extends CFormModel{ public $username; public $password; public $rememberMe=false; private $_identity; public function rules() { return array( array('username, password', 'required'), array('rememberMe', 'boolean'), array('password', 'authenticate'), ); } public function authenticate($attribute,$params) { $this->_identity=new UserIdentity($this->username,$this->password); if(!$this->_identity->authenticate()) $this->addError('password','錯誤的使用者名稱或密碼。'); }}
上述程式碼指定:username
和 password
為必填項, password
應被驗證(authenticated),rememberMe
應該是一個布林值。
rules()
返回的每個規則必須是以下格式:
array('AttributeList', 'Validator', 'on'=>'ScenarioList', ...附加選項)
其中 AttributeList(特性列表)
是需要通過此規則驗證的特性列表字串,每個特性名字由逗號分隔;Validator(驗證器)
指定要執行驗證的種類;on
引數是可選的,它指定此規則應被應用到的場景列表;
附加選項是一個名值對陣列,用於初始化相應驗證器的屬性值。
有三種方式可在驗證規則中指定 Validator
。第一, Validator
可以是模型類中一個方法的名字,就像上面示例中的authenticate
。驗證方法必須是下面的結構:
/** * @param string 所要驗證的特性的名字 * @param array 驗證規則中指定的選項 */public function ValidatorName($attribute,$params) { ... }
第二,Validator
可以是一個驗證器類的名字,當此規則被應用時,
一個驗證器類的例項將被建立以執行實際驗證。規則中的附加選項用於初始化例項的屬性值。 驗證器類必須繼承自 CValidator。
第三,Validator
可以是一個預定義的驗證器類的別名。在上面的例子中, required
名字是 CRequiredValidator 的別名,它用於確保所驗證的特性值不為空。
下面是預定義的驗證器別名的完整列表:
==========================================================================================================================
1.資料訪問物件 (DAO)
Yii DAO 主要包含如下四個類:
- CDbConnection: 代表一個資料庫連線。
- CDbCommand: 代表一條執行的 SQL 語句。
- CDbDataReader: 代表一個只向前移動的,來自一個查詢結果集中的行的流。
- CDbTransaction: 代表一個資料庫事務。
建立資料庫連線
3.DSN 的格式取決於所使用的 PDO 資料庫驅動。總體來說, DSN 要含有 PDO 驅動的名字,跟上一個冒號,再跟上驅動特定的連線語法。下面是一個常用DSN格式的列表。
-
SQLite:
sqlite:/path/to/dbfile
-
MySQL:
mysql:host=localhost;dbname=testdb
-
PostgreSQL:
pgsql:host=localhost;port=5432;dbname=testdb
-
SQL Server:
mssql:host=localhost;dbname=testdb
-
Oracle:
oci:dbname=//localhost:1521/testdb
由於 CDbConnection 繼承自 CApplicationComponent,我們也可以將其作為一個 應用元件 使用。要這樣做的話,
請在 應用配置 中配置一個 db
(或其他名字)應用元件如下:
array( ...... 'components'=>array( ...... 'db'=>array( 'class'=>'CDbConnection', 'connectionString'=>'mysql:host=localhost;dbname=testdb', 'username'=>'root', 'password'=>'password', 'emulatePrepare'=>true, // needed by some MySQL installations ), ), )
Yii::app()->db
訪問資料庫連線了。它已經被自動啟用了執行 SQL 語句
資料庫連線建立後,SQL 語句就可以通過使用 CDbCommand 執行了。你可以通過使用指定的SQL語句作為引數呼叫CDbConnection::createCommand() 建立一個 CDbCommand 例項。
$connection=Yii::app()->db; // 假設你已經建立了一個 "db" 連線// 如果沒有,你可能需要顯式建立一個連線:// $connection=new CDbConnection($dsn,$username,$password);$command=$connection->createCommand($sql); // 如果需要,此 SQL 語句可通過如下方式修改:// $command->text=$newSQL;
一條 SQL 語句會通過 CDbCommand 以如下兩種方式被執行:
-
execute(): 執行一個無查詢 (non-query)SQL語句, 例如
INSERT
,UPDATE
和DELETE
。如果成功,將返回此執行所影響的行數。 -
query(): 執行一條會返回若干行資料的 SQL 語句,例如
SELECT
。 如果成功,它將返回一個 CDbDataReader 例項,通過此例項可以遍歷資料的結果行。為簡便起見, (Yii)還實現了一系列queryXXX()
方法以直接返回查詢結果。
$rowCount=$command->execute(); // 執行無查詢 SQL$dataReader=$command->query(); // 執行一個 SQL 查詢$rows=$command->queryAll(); // 查詢並返回結果中的所有行$row=$command->queryRow(); // 查詢並返回結果中的第一行$column=$command->queryColumn(); // 查詢並返回結果中的第一列$value=$command->queryScalar(); // 查詢並返回結果中第一行的第一個欄位
獲取查詢結果
在 CDbCommand::query() 生成 CDbDataReader 例項之後,可以通過重複呼叫 CDbDataReader::read() 獲取結果中的行。你也可以在
PHP 的 foreach
語言結構中使用 CDbDataReader 一行行檢索資料。
$dataReader=$command->query(); // 重複呼叫 read() 直到它返回 falsewhile(($row=$dataReader->read())!==false) { ... }// 使用 foreach 遍歷資料中的每一行foreach($dataReader as $row) { ... }// 一次性提取所有行到一個陣列$rows=$dataReader->readAll();
使用事務
當一個應用要執行幾條查詢,(每條查詢要從資料庫中讀取/或向資料庫中寫入資訊時) 保證所有sql語句都執行很重要。 事務,在 Yii 中表現為 CDbTransaction 例項,可能會在下面的情況中啟動:
- 開始事務.
- 一個個執行查詢。任何對資料庫的更新對外界不可見。
- 提交事務。如果事務成功,更新變為可見。
- 如果查詢中的一個失敗,整個事務回滾。
上述工作流可以通過如下程式碼實現:
$transaction=$connection->beginTransaction(); try{ $connection->createCommand($sql1)->execute(); $connection->createCommand($sql2)->execute(); //.... other SQL executions $transaction->commit(); //提交事務}catch(Exception $e){ $transaction->rollBack();//回滾事務}
繫結引數(即是變數)
要避免 SQL 注入攻擊 並提高重複執行的 SQL 語句的效率, 你可以 "準備(prepare)"一條含有可選引數佔位符的 SQL 語句,在引數繫結時,這些佔位符將被替換為實際的引數。
引數佔位符可以是命名的 (表現為一個唯一的標記) 或未命名的 (表現為一個問號)。呼叫 CDbCommand::bindParam() 或CDbCommand::bindValue() 以使用實際引數替換這些佔位符。 這些引數不需要使用引號引起來:底層的資料庫驅動會為你搞定這個。 引數繫結必須在 SQL 語句執行之前完成。
// 一條帶有兩個佔位符 ":username" 和 ":email"的 SQL
$sql="INSERT INTO tbl_user (username, email) VALUES(:username,:email)"; $command=$connection->createCommand($sql); // 用實際的使用者名稱替換佔位符 ":username" $command->bindParam(":username",$username,PDO::PARAM_STR); // 用實際的 Email 替換佔位符 ":email" $command->bindParam(":email",$email,PDO::PARAM_STR); $command->execute(); // 使用新的引數集插入另一行 $command->bindParam(":username",$username2,PDO::PARAM_STR); $command->bindParam(":email",$email2,PDO::PARAM_STR); $command->execute();
方法 bindParam() 和 bindValue() 非常相似。唯一的區別就是前者使用一個 PHP 變數繫結引數, 而後者使用一個值。對於那些記憶體中的大資料塊引數,處於效能的考慮,應優先使用前者。
繫結列
當獲取查詢結果時,你也可以使用 PHP 變數繫結列。 這樣在每次獲取查詢結果中的一行時就會自動使用最新的值填充。
$sql="SELECT username, email FROM tbl_user"; $dataReader=$connection->createCommand($sql)->query(); // 使用 $username 變數繫結第一列 (username) $dataReader->bindColumn(1,$username);// 使用 $email 變數繫結第二列 (email) $dataReader->bindColumn(2,$email); while($dataReader->read()!==false){ // $username 和 $email 含有當前行中的 username 和 email }
使用表字首(區分作用)
從版本 1.1.0 起, Yii 提供了整合了對使用表字首的支援。 表字首是指在當前連線的資料庫中的資料表的名字前面新增的一個字串。 它常用於共享的伺服器環境,這種環境中多個應用可能會共享同一個資料庫,要使用不同的表字首以相互區分。 例如,一個應用可以使用 tbl_
作為表字首而另一個可以使用 yii_
要使用表字首,配置 CDbConnection::tablePrefix 屬性為所希望的表字首。
然後,在 SQL 語句中使用 {{TableName}}
代表表的名字,其中的 TableName
是指不帶字首的表名。
例如,如果資料庫含有一個名為 tbl_user
的表,而 tbl_
被配置為表字首,那我們就可以使用如下程式碼執行使用者相關的查詢:
$sql='SELECT * FROM {{user}}'; //對應表tbl_user
$users=$connection->createCommand($sql)->queryAll();
2.Active Record
簡單起見,我們使用下面的資料表作為此節中的例子。注意,如果你使用 MySQL 資料庫,你應該將下面的 SQL 中的 AUTOINCREMENT
替換為 AUTO_INCREMENT
。
CREATE TABLE tbl_post ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, title VARCHAR(128) NOT NULL, content TEXT NOT NULL, create_time INTEGER NOT NULL);
db
的應用元件,或者如果你想使用
AR 處理多個資料庫,你應該覆蓋CActiveRecord::getDbConnection()。 CActiveRecord 類是所有
AR 類的基類。定義 AR 類
要訪問一個資料表,我們首先需要通過整合 CActiveRecord 定義一個
AR 類。 每個 AR 類代表一個單獨的資料表,一個 AR 例項則代表那個表中的一行。 如下例子演示了代表 tbl_post
表的
AR 類的最簡程式碼:
class Post extends CActiveRecord{ public static function model($className=__CLASS__) { return parent::model($className); } //認情況下,AR 類的名字和資料表的名字相同。如果不同,請覆蓋 tableName() 方法。 model() 方法為每個 AR 類宣告為如此(稍後解釋) public function tableName() { return 'tbl_post'; }}
tbl_post
表中插入一個新行$post=new Post;
//從未在Post
類中顯式定義屬性title
,但通過上述程式碼訪問。 因為title
是tbl_post
表中的一個列,CActiveRecord 通過PHP的__get()
魔術方法使其成為一個可訪問的屬性$post->title='sample post'; //如果我們嘗試以同樣的方式訪問一個不存在的列,將會丟擲一個異常$post->content='post body content'; $post->save();
AR 依靠表中良好定義的主鍵。如果一個表沒有主鍵,則必須在相應的 AR 類中通過如下方式覆蓋 primaryKey()
方法指定哪一列或哪幾列作為主鍵。
public function primaryKey(){ return 'id'; // 對於複合主鍵,要返回一個類似如下的陣列 // return array('pk1', 'pk2');}
建立記錄
要向資料表中插入新行,我們要建立一個相應 AR 類的例項,設定其與表的列相關的屬性,然後呼叫 save() 方法完成插入:
$post=new Post; $post->title='sample post'; $post->content='content for the sample post'; $post->create_time=time(); $post->save();
如果表的主鍵是自增的,在插入完成後,AR 例項將包含一個更新的主鍵。在上面的例子中, id
屬性將反映出新插入帖子的主鍵值,即使我們從未顯式地改變它。
如果一個列在表結構中使用了靜態預設值(例如一個字串,一個數字)定義。則 AR 例項中相應的屬性將在此例項建立時自動含有此預設值。改變此預設值的一個方式就是在 AR 類中顯示定義此屬性:
class Post extends CActiveRecord{ public $title='please enter a title'; ...... } $post=new Post; echo $post->title; // 這兒將顯示: please enter a title
從版本 1.0.2 起,記錄在儲存(插入或更新)到資料庫之前,其屬性可以賦值為 CDbExpression 型別。
例如,為儲存一個由 MySQL 的 NOW()
函式返回的時間戳,我們可以使用如下程式碼:
$post=new Post; $post->create_time=new CDbExpression('NOW()'); // $post->create_time='NOW()'; 不會起作用,因為// 'NOW()' 將會被作為一個字串處理。$post->save();
提示: 由於 AR 允許我們無需寫一大堆 SQL 語句就能執行資料庫操作, 我們經常會想知道 AR 在背後到底執行了什麼 SQL 語句。這可以通過開啟 Yii 的 日誌功能 實現。例如,我們在應用配置中開啟了 CWebLogRoute ,我們將會在每個網頁的最後看到執行過的 SQL 語句。 從 1.0.5 版本起,我們可以在應用配置中設定CDbConnection::enableParamLogging 為 true ,這樣繫結在 SQL 語句中的引數值也會被記錄。
讀取記錄
條件的結果中的第一行$post=Post::model()->find($condition,$params);
// 查詢具有指定主鍵值的那一行 $post=Post::model()->findByPk($postID,$condition,$params); // 查詢具有指定屬性值的行 $post=Post::model()->findByAttributes($attributes,$condition,$params); // 通過指定的 SQL 語句查詢結果中的第一行 $post=Post::model()->findBySql($sql,$params);
如上所示,通過 Post::model()
呼叫 find
方法。
靜態方法 model()
是每個
AR 類所必須的。 此方法返回在物件上下文中的一個用於訪問類級別方法(類似於靜態類方法的東西)的 AR 例項。
如果 find
方法找到了一個滿足查詢條件的行,它將返回一個 Post
例項,例項的屬性含有資料錶行中相應列的值。
然後就可以像讀取普通物件的屬性那樣讀取載入的值,例如 echo
$post->title;
。
如果使用給定的查詢條件在資料庫中沒有找到任何東西, find
方法將返回
null 。
呼叫 find
時,我們使用 $condition
和 $params
指定查詢條件。此處 $condition
可以是
SQL 語句中的 WHERE
字串,$params
則是一個引數陣列,其中的值應繫結到 $condation
中的佔位符。例如:
// 查詢 postID=10 的那一行 $post=Post::model()->find('postID=:postID', array(':postID'=>10));
注意: 在上面的例子中,我們可能需要在特定的 DBMS 中將
postID
列的引用進行轉義。 例如,如果我們使用 PostgreSQL,我們必須將此表示式寫為"postID"=:postID
,因為 PostgreSQL 在預設情況下對列名大小寫不敏感。
我們也可以使用 $condition
指定更復雜的查詢條件。
不使用字串,我們可以讓 $condition
成為一個 CDbCriteria 的例項,它允許我們指定不限於 WHERE
的條件。
例如:
$criteria=new CDbCriteria; $criteria->select='title'; // 只選擇 'title' 列$criteria->condition='postID=:postID'; $criteria->params=array(':postID'=>10); $post=Post::model()->find($criteria); // $params 不需要了
注意,當使用 CDbCriteria 作為查詢條件時,$params
引數不再需要了,因為它可以在 CDbCriteria 中指定,就像上面那樣。
一種替代 CDbCriteria 的方法是給 find
方法傳遞一個陣列。
陣列的鍵和值各自對應標準(criterion)的屬性名和值,上面的例子可以重寫為如下:
$post=Post::model()->find(array( 'select'=>'title', 'condition'=>'postID=:postID', 'params'=>array(':postID'=>10), ));
資訊: 當一個查詢條件是關於按指定的值匹配幾個列時,我們可以使用 findByAttributes()。我們使
$attributes
引數是一個以列名做索引的值的陣列。在一些框架中,此任務可以通過呼叫類似findByNameAndTitle
的方法實現。雖然此方法看起來很誘人, 但它常常引起混淆,衝突和比如列名大小寫敏感的問題。
當有多行資料匹配指定的查詢條件時,我們可以通過下面的 findAll
方法將他們全部帶回。
每個都有其各自的 find
方法,就像我們已經講過的那樣。
// 查詢滿足指定條件的所有行$posts=Post::model()->findAll($condition,$params); // 查詢帶有指定主鍵的所有行$posts=Post::model()->findAllByPk($postIDs,$condition,$params); // 查詢帶有指定屬性值的所有行$posts=Post::model()->findAllByAttributes($attributes,$condition,$params); // 通過指定的SQL語句查詢所有行$posts=Post::model()->findAllBySql($sql,$params);
如果沒有任何東西符合查詢條件,findAll
將返回一個空陣列。這跟 find
不同,find
會在沒有找到什麼東西時返回
null。
除了上面講述的 find
和 findAll
方法,為了方便,(Yii)還提供瞭如下方法:
// 獲取滿足指定條件的行數$n=Post::model()->count($condition,$params); // 通過指定的 SQL 獲取結果行數$n=Post::model()->countBySql($sql,$params); // 檢查是否至少有一行復合指定的條件$exists=Post::model()->exists($condition,$params);
更新記錄
在 AR 例項填充了列的值之後,我們可以改變它們並把它們存回資料表。
$post=Post::model()->findByPk(10); $post->title='new post title'; $post->save(); // 將更改儲存到資料庫
正如我們可以看到的,我們使用同樣的 save() 方法執行插入和更新操作。
如果一個 AR 例項是使用 new
操作符建立的,呼叫save() 將會向資料表中插入一行新資料;
如果 AR 例項是某個 find
或 findAll
方法的結果,呼叫 save() 將更新表中現有的行。
實際上,我們是使用 CActiveRecord::isNewRecord 說明一個
AR 例項是不是新的。
直接更新資料表中的一行或多行而不首先載入也是可行的。 AR 提供瞭如下方便的類級別方法實現此目的:
// 更新符合指定條件的行Post::model()->updateAll($attributes,$condition,$params); // 更新符合指定條件和主鍵的行Post::model()->updateByPk($pk,$attributes,$condition,$params); // 更新滿足指定條件的行的計數列Post::model()->updateCounters($counters,$condition,$params);
在上面的程式碼中, $attributes
是一個含有以
列名作索引的列值的陣列; $counters
是一個由列名索引的可增加的值的陣列;$condition
和 $params
在前面的段落中已有描述。
刪除記錄
如果一個 AR 例項被一行資料填充,我們也可以刪除此行資料。
$post=Post::model()->findByPk(10); // 假設有一個帖子,其 ID 為 10$post->delete(); // 從資料表中刪除此行
注意,刪除之後, AR 例項仍然不變,但資料表中相應的行已經沒了。
使用下面的類級別程式碼,可以無需首先載入行就可以刪除它。
// 刪除符合指定條件的行Post::model()->deleteAll($condition,$params); // 刪除符合指定條件和主鍵的行Post::model()->deleteByPk($pk,$condition,$params);
資料驗證
當插入或更新一行時,我們常常需要檢查列的值是否符合相應的規則。 如果列的值是由終端使用者提供的,這一點就更加重要。總體來說,我們永遠不能相信任何來自客戶端的資料。
當呼叫 save() 時, AR 會自動執行資料驗證。 驗證是基於在 AR 類的 rules() 方法中指定的規則進行的。 關於驗證規則的更多詳情,請參考 宣告驗證規則 一節。 下面是儲存記錄時所需的典型的工作流。
if($post->save()){ // 資料有效且成功插入/更新}else{ // 資料無效,呼叫 getErrors() 提取錯誤資訊}
當要插入或更新的資料由終端使用者在一個 HTML 表單中提交時,我們需要將其賦給相應的 AR 屬性。 我們可以通過類似如下的方式實現:
$post->title=$_POST['title']; $post->content=$_POST['content']; $post->save();
如果有很多列,我們可以看到一個用於這種複製的很長的列表。 這可以通過使用如下所示的 attributes 屬性簡化操作。 更多資訊可以在 安全的特性賦值 一節和 建立動作 一節找到。
// 假設 $_POST['Post'] 是一個以列名索引列值為值的陣列$post->attributes=$_POST['Post']; $post->save();
對比記錄
類似於表記錄,AR 例項由其主鍵值來識別。 因此,要對比兩個 AR 例項,假設它們屬於相同的 AR 類, 我們只需要對比它們的主鍵值。 然而,一個更簡單的方式是呼叫 CActiveRecord::equals()。
資訊: 不同於 AR 在其他框架的執行, Yii 在其 AR 中支援多個主鍵. 一個複合主鍵由兩個或更多欄位構成。相應地, 主鍵值在 Yii 中表現為一個陣列. primaryKey 屬性給出了一個 AR 例項的主鍵值。
自定義
CActiveRecord 提供了幾個佔位符方法,它們可以在子類中被覆蓋以自定義其工作流。
- beforeValidate 和
-
beforeSave 和 afterSave: 這兩個將在儲存 AR 例項之前和之後被呼叫。
-
beforeDelete 和 afterDelete: 這兩個將在一個 AR 例項被刪除之前和之後被呼叫。
-
afterConstruct: 這個將在每個使用
new
操作符建立 AR 例項後被呼叫。 -
beforeFind: 這個將在一個 AR 查詢器被用於執行查詢(例如
find()
,findAll()
)之前被呼叫。 1.0.9 版本開始可用。 -
afterFind: 這個將在每個 AR 例項作為一個查詢結果建立時被呼叫。
使用 AR 處理事務
每個 AR 例項都含有一個屬性名叫 dbConnection ,是一個 CDbConnection 的例項,這樣我們可以在需要時配合 AR 使用由 Yii DAO 提供的 事務 功能:
$model=Post::model(); $transaction=$model->dbConnection->beginTransaction(); try{ // 查詢和儲存是可能由另一個請求干預的兩個步驟 // 這樣我們使用一個事務以確保其一致性和完整性 $post=$model->findByPk(10); $post->title='new post title'; $post->save(); $transaction->commit(); }catch(Exception $e){ $transaction->rollBack(); }
命名範圍
Note: 對命名範圍的支援從版本 1.0.5 開始。 命名範圍的最初想法來源於 Ruby on Rails.
命名範圍(named scope) 表示一個 命名的(named) 查詢規則,它可以和其他命名範圍聯合使用並應用於 Active Record 查詢。
命名範圍主要是在 CActiveRecord::scopes() 方法中以名字-規則對的方式宣告。
如下程式碼在 Post
模型類中宣告瞭兩個命名範圍, published
和 recently
。
class Post extends CActiveRecord{ ...... public function scopes() { return array( 'published'=>array( 'condition'=>'status=1', ), 'recently'=>array( 'order'=>'create_time DESC', 'limit'=>5, ), ); }}
每個命名範圍宣告為一個可用於初始化 CDbCriteria 例項的陣列。
例如,recently
命名範圍指定 order
屬性為create_time
DESC
, limit
屬性為
5。他們翻譯為查詢規則後就會返回最近的5篇帖子。
命名範圍多用作 find
方法呼叫的修改器。
幾個命名範圍可以鏈到一起形成一個更有約束性的查詢結果集。例如, 要找到最近釋出的帖子, 我們可以使用如下程式碼:
$posts=Post::model()->published()->recently()->findAll();
總體來說,命名範圍必須出現在一個 find
方法呼叫的左邊。
它們中的每一個都提供一個查詢規則,並聯合到其他規則, 包括傳遞給 find
方法呼叫的那一個。
最終結果就像給一個查詢新增了一系列過濾器。
從版本 1.0.6 開始,命名範圍也可用於 update
和 delete
方法。
例如,如下程式碼將刪除所有最近釋出的帖子:
Post::model()->published()->recently()->delete();
注意: 命名範圍只能用於類級別方法。也就是說,此方法必須使用
ClassName::model()
呼叫。
引數化的命名範圍
命名範圍可以引數化。例如, 我們想自定義 recently
命名範圍中指定的帖子數量,要實現此目的,不是在CActiveRecord::scopes 方法中宣告命名範圍,
而是需要定義一個名字和此命名範圍的名字相同的方法:
public function recently($limit=5){ $this->getDbCriteria()->mergeWith(array( 'order'=>'create_time DESC', 'limit'=>$limit, )); return $this; }
然後,我們就可以使用如下語句獲取3條最近釋出的帖子。
$posts=Post::model()->published()->recently(3)->findAll();
上面的程式碼中,如果我們沒有提供引數 3,我們將預設獲取 5 條最近釋出的帖子。
預設的命名範圍
模型類可以有一個預設命名範圍,它將應用於所有 (包括相關的那些) 關於此模型的查詢。例如,一個支援多種語言的網站可能只想顯示當前使用者所指定的語言的內容。 因為可能會有很多關於此網站內容的查詢, 我們可以定義一個預設的命名範圍以解決此問題。 為實現此目的,我們覆蓋 CActiveRecord::defaultScope 方法如下:
class Content extends CActiveRecord{ public function defaultScope() { return array( 'condition'=>"language='".Yii::app()->language."'", ); }}
現在,如果下面的方法被呼叫,將會自動使用上面定義的查詢規則:
$contents=Content::model()->findAll();
注意,預設的命名範圍只會應用於 SELECT
查詢。INSERT
, UPDATE
和 DELETE
查詢將被忽略。
驗證和授權
Yii::app()->user
在任何地方訪問定義身份類
不同的類可能實現不同的驗證方式(例如:OpenID,LDAP)。最好是繼承 CUserIdentity,此類是居於使用者名稱和密碼的驗證方式。定義身份類的主要工作是實現IUserIdentity::authenticate方法。在使用者會話中根據需要,身份類可能需要定義別的身份資訊
getId
函式來返回驗證過程中獲得的_id
變數(預設的實現則是返回使用者名稱)。登入和登出
使用身份類和使用者部件,我們方便的實現登入和登出。
// 使用提供的使用者名稱和密碼登入使用者$identity=new UserIdentity($username,$password); if($identity->authenticate()) Yii::app()->user->login($identity); else echo $identity->errorMessage; ...... // 登出當前使用者Yii::app()->user->logout();
基於Cookie 的登入
授權處理結果
訪問控制過濾器
概覽(Overview)
配置授權管理器
定義授權等級體系
使用業務規則
許可權檢查
使用預設角色
Yii::app() 返回在index.php中建立的CWebApplication例項
主要負責一些全域性性的功能模組
比如Yii::app()->getUser()返回的是CWebUser例項(用於表達當前使用者的驗證資訊)
在index.php使用的配置檔案,其實質就是對Yii::app()進行屬性的初始化
關於CComponent的說明,這是Yii的基石
Yii::app()->ComponentID
,其中的 ComponentID
是指元件的ID(例如Yii::app()->cache
)。
- $trans = Yii::app()->db->beginTransaction();
- try {
- $manufacturer = new Manufacturer();
- $manufacturer->name = $name;
- $manufacturer->email = $email;
- $manufacturer->save();
- $trans->commit();
- } catch (Exception $e) {
- $trans->rollback();
- $this->response(array('status' => 1, 'msg' => $e->getMessage()));
- }
$transaction=$connection->beginTransaction(); try{ $connection->createCommand($sql1)->execute(); $connection->createCommand($sql2)->execute(); //.... other SQL executions $transaction->commit(); }catch(Exception $e) // 如果有一條查詢失敗,則會丟擲異常{ $transaction->rollBack(); }
雜談:
IAuthManager->createAuthItem
\
CApplicationComponent
\
CAuthManager->createRole call createAuthItem
\
CDbAuthManager ->implents createAuthItem
相關文章
- 讀書筆記...筆記
- 讀書筆記筆記
- 《讀書與做人》讀書筆記筆記
- Cucumber讀書筆記筆記
- 散文讀書筆記筆記
- HTTP 讀書筆記HTTP筆記
- CoreJava讀書筆記-------Java筆記
- flask讀書筆記Flask筆記
- Vue讀書筆記Vue筆記
- MONGODB 讀書筆記MongoDB筆記
- Qt讀書筆記QT筆記
- Node讀書筆記筆記
- SAP讀書筆記筆記
- iptables 讀書筆記筆記
- Makefile 讀書筆記筆記
- mysql讀書筆記MySql筆記
- 鎖讀書筆記筆記
- dataguard讀書筆記筆記
- 讀書筆記3筆記
- 讀書筆記2筆記
- postgres 讀書筆記筆記
- 《重構》讀書筆記筆記
- webpackDemo讀書筆記Web筆記
- PMBook讀書筆記(一)筆記
- Effective Java 讀書筆記Java筆記
- js高程讀書筆記JS筆記
- “Docker Practice”讀書筆記Docker筆記
- FPGA讀書筆記5FPGA筆記
- FPGA讀書筆記3FPGA筆記
- FPGA讀書筆記4FPGA筆記
- FPGA讀書筆記2FPGA筆記
- FPGA讀書筆記1FPGA筆記
- 《精通JavaScript》讀書筆記JavaScript筆記
- 讀書筆記摘錄:筆記
- 《矽谷之父》讀書筆記筆記
- 重構讀書筆記筆記
- 讀書筆記之一筆記
- Spam Or Ham讀書筆記筆記