鍍金池/ 教程/ PHP/ Yii Framework 開發(fā)教程(8) 使用 FormModel
Yii Framework 開發(fā)教程(16) UI 組件 StarRating 示例
Yii Framework 開發(fā)教程(2) Yii Web 應(yīng)用基礎(chǔ)
Yii Framework 開發(fā)教程(19) UI 組件 TreeView 示例
Yii Framework 開發(fā)教程(39) Zii 組件-Slider 示例
Yii Framework 開發(fā)教程(45) Zii 組件-Selectable 示例
Yii Framework 開發(fā)教程(44) Zii 組件-Resizable 示例
Yii Framework 開發(fā)教程(8) 使用 FormModel
Yii Framework 開發(fā)教程(42) Zii 組件-Draggable 示例
Yii Framework 開發(fā)教程(18) UI 組件 TextHighlighter 示例
Yii Framework 開發(fā)教程(32) Zii 組件-GridView 示例
Yii Framework 開發(fā)教程(30) Zii 組件-ListView 示例
Yii Framework 開發(fā)教程(9) UI 組件 Widget 概述
Yii Framework 開發(fā)教程(17) UI 組件 TabView 示例
Yii Framework 開發(fā)教程(24) 數(shù)據(jù)庫-DAO 示例
Yii Framework 開發(fā)教程(25) 數(shù)據(jù)庫-Query Builder 示例
Yii Framework 開發(fā)教程(21) UI 組件 自定義 Captcha 示例
Yii Framework 開發(fā)教程(38) Zii 組件-ProgressBar 示例
Yii Framework 開發(fā)教程(20) UI 組件 Captcha 示例
Yii Framework 開發(fā)教程(14) UI 組件 MaskedTextField 示例
Yii Framework 開發(fā)教程(22) UI 組件 Zii 組件簡介
Yii Framework 開發(fā)教程(31) Zii 組件-DetailView 示例
Yii Framework 開發(fā)教程(33) Zii 組件-Accordion 示例
Yii Framework 開發(fā)教程(36) Zii 組件-DatePicker 示例
Yii Framework 開發(fā)教程(6) CComponent 組件
Yii Framework 開發(fā)教程(37) Zii 組件-Dialog 示例
Yii Framework 開發(fā)教程(26) 數(shù)據(jù)庫-Active Record 示例
Yii Framework 開發(fā)教程(29) Zii組件-Menu 示例
Yii Framework 開發(fā)教程(46) Zii 組件-Sortable 示例
Yii Framework 開發(fā)教程(10) UI 組件 自定義組件
Yii Framework 開發(fā)教程(11) UI 組件 ActiveForm 示例
Yii Framework 開發(fā)教程(43) Zii 組件-Droppable 示例
Yii Framework 開發(fā)教程(27) 數(shù)據(jù)庫-關(guān)聯(lián) Active Record 示例
Yii Framework 開發(fā)教程(47) 主題 Theme 示例
Yii Framework 開發(fā)教程(48) 多國語言示例
Yii Framework 開發(fā)教程(35) Zii 組件-Button 示例
Yii Framework 開發(fā)教程(3) 為應(yīng)用添加日志
Yii Framework 開發(fā)教程(23) 數(shù)據(jù)庫-概述
Yii Framework 開發(fā)教程(12) UI 組件 ClipWidget 示例
Yii Framework 開發(fā)教程(41) Zii 組件-Tabs 示例
Yii Framework 開發(fā)教程(34) Zii 組件-AutoComplete 示例
Yii Framework 開發(fā)教程(40) Zii 組件-SliderInput 示例
Yii Framework 開發(fā)教程(5) URL 管理
Yii Framework 開發(fā)教程(4) Hangman 猜單詞游戲?qū)嵗?/span>
Yii Framework 開發(fā)教程(15) UI 組件 MultiFileUpload 示例
Yii Framework 開發(fā)教程(7) 使用 CHtml 創(chuàng)建 Form
Yii Framework 開發(fā)教程(28) Data Provider 簡介
Yii Framework 開發(fā)教程(1) 第一個應(yīng)用 Hello World
Yii Framework 開發(fā)教程(13) UI 組件 ContentDecorator 示例

Yii Framework 開發(fā)教程(8) 使用 FormModel

Contents

  1. 定義模型類
  2. 聲明驗證規(guī)則
  3. 安全的特性賦值
    3.1 1.1 中的安全特性
    3.2 1.0 中的安全特性
  4. 觸發(fā)驗證
  5. 提取驗證錯誤
  6. 特性標(biāo)簽
  7. 創(chuàng)建動作Action方法
  8. 構(gòu)建視圖

通過前面的學(xué)習(xí),我們了解了 Yii Web 應(yīng)用的基本組成部分,也會編寫像 Hangman 猜單詞游戲這樣簡單的應(yīng)用。在第一個例子 Yii Framework 開發(fā)簡明教程(1) 第一個應(yīng)用Hello World 我們介紹了 Yii Web 應(yīng)用采用 MVC 模型,也說明了本教程目的是通過不同的視角(主要是通過開發(fā) Windows 應(yīng)用 C++,C#程序員的角度)幫助 Windows 桌面應(yīng)用或 ASP.Net 程序員較快的掌握 PHP Yii Framework 應(yīng)用程序框架。

前面我們介紹了通過 CHtml 創(chuàng)建 View(頁面視圖 Form),通過 CController 來處理用戶提交事件,和 Windows 桌面應(yīng)用或 ASP.Net 做個類比, Yii 中視圖 View (HTML Form) 類似于 WinForm 或是 Asp.Net 的 Page。 控制類 Controller 類似 Windows 桌面應(yīng)用或 Asp.Net 的事件處理(Code-Behind)類。不同的是 Asp.Net 和 Windows 桌面應(yīng)用可以為 UI 中各個 UI 組件,比如文本框,按鈕定義 Id,然后為不同的 UI 組件添加事件處理。PHP 應(yīng)用或是 Yii 應(yīng)用沒有對應(yīng)的機(jī)制可以為定義在 HTML Form 中的 UI 組件定義一個 Id,并為 UI 組件定義事件處理。 然而 Yii 框架提供了 CFormModel 可以支持類似的功能,簡單的說,通過 CFormModel,可以為 HTML Form 中的 UI 小組件定義變量,并且可以在其控制類 Controller 中訪問這些變量。每個 Yii View(Form)一般都提供一個“提交”按鈕(Submit Button),用戶點(diǎn)擊這個“提交按鈕”觸發(fā) CController對象對應(yīng)的 actionXXX 方法,在 actionXXX 方法中可以通過 CFormModel 來訪問 HTML Form 的 UI 組件的值。

前面教程中說過 Yii 中的模型(Model)是 CModel 或其子類的實例。模型用于保持?jǐn)?shù)據(jù)以及與其相關(guān)的業(yè)務(wù)邏輯,

Yii 實現(xiàn)了兩種類型的模型:表單模型和 Active Record。二者均繼承于相同的基類 CModel

表單模型是 CFormModel 的實例。表單模型用于保持從用戶的輸入獲取的數(shù)據(jù)。 這些數(shù)據(jù)經(jīng)常被獲取,使用,然后丟棄。例如,在一個登錄頁面中, 我們可以使用表單模型用于表示由最終用戶提供的用戶名和密碼信息。更多詳情,請參考 使用表單。本篇介紹 CFormModel 的用法,

Active Record (AR) 是一種用于通過面向?qū)ο蟮娘L(fēng)格抽象化數(shù)據(jù)庫訪問的設(shè)計模式。 每個 AR 對象是一個 CActiveRecord 或其子類的實例。代表數(shù)據(jù)表中的一行。 行中的字段對應(yīng) AR 對象中的屬性。更多關(guān)于 AR 的細(xì)節(jié)請閱讀 Active Record. 后面介紹數(shù)據(jù)庫使用時再介紹。

本篇使用一個簡單的登錄界面來介紹 FormModel 的用法,本例下載。

1. 定義模型類

下面我們創(chuàng)建了一個 LoginForm (protected/models/LoginForm.php) 模型類用于在一個登錄頁中收集用戶的輸入。 由于登錄信息只被用于驗證用戶,并不需要保存,因此我們將 LoginForm 創(chuàng)建為一個表單模型。

    class LoginForm extends CFormModel
    {
       public $username;
       public $password;
       public $rememberMe=false;
    }

LoginForm 中定義了三個屬性: $username, $password 和 $rememberMe。他們用于保存用戶輸入的用戶名和密碼,還有用戶是否想記住他的登錄的選項。 由于 $rememberMe 有一個默認(rèn)的值 false,相應(yīng)的選項在初始化顯示在登錄表單中時將是未勾選狀態(tài)。

信息: 我們將這些成員變量稱為 特性(attributes) 而不是 屬性(properties),以區(qū)別于普通的
屬性(properties)。 特性(attribute)是一個主要用于存儲來自用戶輸入或數(shù)據(jù)庫數(shù)據(jù)的屬性
(propertiy)。

2. 聲明驗證規(guī)則

一旦用戶提交了他的輸入,模型被填充,我們就需要在使用前確保用戶的輸入是有效的。 這是通過將用戶的輸入和一系列規(guī)則執(zhí)行驗證實現(xiàn)的。我們在 rules() 方法中指定這些驗證規(guī)則, 此方法應(yīng)返回一個規(guī)則配置數(shù)組。

    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 應(yīng)被驗證(authenticated),rememberMe 應(yīng)該是一個布爾值。

rules() 返回的每個規(guī)則必須是以下格式:

    array('AttributeList', 'Validator', 'on'=>'ScenarioList', ...附加選項)

其中 AttributeList(特性列表) 是需要通過此規(guī)則驗證的特性列表字符串,每個特性名字由逗號分隔;Validator(驗證器) 指定要執(zhí)行驗證的種類;on 參數(shù)是可選的,它指定此規(guī)則應(yīng)被應(yīng)用到的場景列表; 附加選項是一個名值對數(shù)組,用于初始化相應(yīng)驗證器的屬性值。

有三種方式可在驗證規(guī)則中指定 Validator 。第一, Validator 可以是模型類中一個方法的名字,就像上面示例中的 authenticate 。驗證方法必須是下面的結(jié)構(gòu):

    /**
     * @param string 所要驗證的特性的名字
     * @param array 驗證規(guī)則中指定的選項
     */
    public function ValidatorName($attribute,$params) { ... }

第二,Validator 可以是一個驗證器類的名字,當(dāng)此規(guī)則被應(yīng)用時, 一個驗證器類的實例將被創(chuàng)建以執(zhí)行實際驗證。規(guī)則中的附加選項用于初始化實例的屬性值。 驗證器類必須繼承自 CValidator。

第三,Validator 可以是一個預(yù)定義的驗證器類的別名。在上面的例子中, required 名字是 CRequiredValidator 的別名,它用于確保所驗證的特性值不為空。 下面是預(yù)定義的驗證器別名的完整列表:

下面我們列出了幾個只用這些預(yù)定義驗證器的示例:

    // 用戶名為必填項
    array('username', 'required'),
    // 用戶名必須在 3 到 12 個字符之間
    array('username', 'length', 'min'=>3, 'max'=>12),
    // 在注冊場景中,密碼password必須和password2一致。
    array('password', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'),
    // 在登錄場景中,密碼必須接受驗證。
    array('password', 'authenticate', 'on'=>'login'),

3. 安全的特性賦值

在一個類的實例被創(chuàng)建后,我們通常需要用最終用戶提交的數(shù)據(jù)填充它的特性。 這可以通過如下塊賦值(massive assignment)方式輕松實現(xiàn):

    $model=new LoginForm;
    if(isset($_POST['LoginForm']))
         $model->attributes=$_POST['LoginForm'];

最后的表達(dá)式被稱作 塊賦值(massive assignment) ,它將 $_POST['LoginForm'] 中的每一項復(fù)制到相應(yīng)的模型特性中。這相當(dāng)于如下賦值方法:

    foreach($_POST['LoginForm'] as $name=>$value)
    {
        if($name 是一個安全的特性)
            $model->$name=$value;
    }

檢測特性的安全非常重要,例如,如果我們以為一個表的主鍵是安全的而暴露了它,那么攻擊者可能就獲得了一個修改記錄的主鍵的機(jī)會, 從而篡改未授權(quán)給他的內(nèi)容。

檢測特性安全的策略在版本 1.0 和 1.1 中是不同的,下面我們將分別講解:

1.1 中的安全特性

在版本 1.1 中,特性如果出現(xiàn)在相應(yīng)場景的一個驗證規(guī)則中,即被認(rèn)為是安全的。 例如:

    array('username, password', 'required', 'on'=>'login, register'),
    array('email', 'required', 'on'=>'register'),

如上所示, username 和 password 特性在 login 場景中是必填項。而 username, password 和 email 特性在 register 場景中是必填項。 于是,如果我們在 login 場景中執(zhí)行塊賦值,就只有 username 和 password 會被塊賦值。 因為只有它們出現(xiàn)在 login 的驗證規(guī)則中。 另一方面,如果場景是 register ,這三個特性就都可以被塊賦值。

    // 在登錄場景中
    $model=new User('login');
    if(isset($_POST['User']))
        $model->attributes=$_POST['User'];``

    // 在注冊場景中
    $model=new User('register');
    if(isset($_POST['User']))
        $model->attributes=$_POST['User'];

那么為什么我們使用這樣一種策略來檢測特性是否安全呢? 背后的基本原理就是:如果一個特性已經(jīng)有了一個或多個可檢測有效性的驗證規(guī)則,那我們還擔(dān)心什么呢?

請記住,驗證規(guī)則是用于檢查用戶輸入的數(shù)據(jù),而不是檢查我們在代碼中生成的數(shù)據(jù)(例如時間戳,自動產(chǎn)生的主鍵)。 因此,不要 為那些不接受最終用戶輸入的特性添加驗證規(guī)則。

有時候,我們想聲明一個特性是安全的,即使我們沒有為它指定任何規(guī)則。 例如,一篇文章的內(nèi)容可以接受用戶的任何輸入。我們可以使用特殊的 safe 規(guī)則實現(xiàn)此目的:

    array('content', 'safe')

為了完成起見,還有一個用于聲明一個屬性為不安全的 unsafe 規(guī)則:

    array('permission', 'unsafe')

unsafe 規(guī)則并不常用,它是我們之前定義的安全特性的一個例外。

1.0 中的安全特性

在版本 1.0 中,決定一個數(shù)據(jù)項是否是安全的,基于一個名為 safeAttributes 方法的返回值和數(shù)據(jù)項被指定的場景. 默認(rèn)的,這個方法返回所有公共成員變量作為 CFormModel 的安全特性,而它也返回了除了主鍵外, 表中所有字段名作為 CActiveRecord 的安全特性.我們可以根據(jù)場景重寫這個方法來限制安全特性 .例如, 一個用戶模型可以包含很多特性,但是在 login 場景.里,我們只能使用 username 和 password 特性.我們可以按照如下來指定這一限制 :

    public function safeattributes()
    {
        return array(
          parent::safeattributes(),
             'login' => 'username, password',
        );
    }

safeAttributes 方法更準(zhǔn)確的返回值應(yīng)該是如下結(jié)構(gòu)的 :

    array(
       // these attributes can be massively assigned in any scenario
       // that is not explicitly specified below
       'attr1, attr2, ...',
         *
       // these attributes can be massively assigned only in scenario 1
       'scenario1' => 'attr2, attr3, ...',
         *
       // these attributes can be massively assigned only in scenario 2
       'scenario2' => 'attr1, attr3, ...',
    )

如果模型不是場景敏感的(比如,它只在一個場景中使用,或者所有場景共享了一套同樣的安全特性),返 回值可以是如下那樣簡單的字符串.

    'attr1, attr2, ...'

而那些不安全的數(shù)據(jù)項,我們需要使用獨(dú)立的賦值語句來分配它們到相應(yīng)的特性.如下所示:

    $model->permission='admin';
    $model->id=1;

4. 觸發(fā)驗證

一旦模型被用戶提交的數(shù)據(jù)填充,我們就可以調(diào)用 CModel::validate() 出發(fā)數(shù)據(jù)驗證進(jìn)程。此方法返回一個指示驗證是否成功的值。 對 CActiveRecord 模型來說,驗證也可以在我們調(diào)用其 CActiveRecord::save() 方法時自動觸發(fā)。

我們可以使用 scenario 設(shè)置場景屬性,這樣,相應(yīng)場景的驗證規(guī)則就會被應(yīng)用。

驗證是基于場景執(zhí)行的。 scenario 屬性指定了模型當(dāng)前用于的場景和當(dāng)前使用的驗證規(guī)則集。 例如,在 login 場景中,我們只想驗證用戶模型中的 username 和 password 輸入; 而在 register 場景中,我們需要驗證更多的輸入,例如 email, address, 等。 下面的例子演示了如何在 register 場景中執(zhí)行驗證:

    // 在注冊場景中創(chuàng)建一個  User 模型。等價于:
    // $model=new User;
    // $model->scenario='register';
    $model=new User('register');

    // 將輸入的值填充到模型
    $model->attributes=$_POST['User'];

    // 執(zhí)行驗證
    if($model->validate())   // if the inputs are valid
        ...
    else
        ...

規(guī)則關(guān)聯(lián)的場景可以通過規(guī)則中的 on 選項指定。如果 on 選項未設(shè)置,則此規(guī)則會應(yīng)用于所有場景。例如:

    public function rules()
    {
        return array(
            array('username, password', 'required'),
            array('password_repeat', 'required', 'on'=>'register'),
            array('password', 'compare', 'on'=>'register'),
        );
    }

第一個規(guī)則將應(yīng)用于所有場景,而第二個將只會應(yīng)用于 register 場景。

5. 提取驗證錯誤

驗證完成后,任何可能產(chǎn)生的錯誤將被存儲在模型對象中。 我們可以通過調(diào)用 CModel::getErrors()CModel::getError() 提取這些錯誤信息。 這兩個方法的不同點(diǎn)在于第一個方法將返回 所有 模型特性的錯誤信息,而第二個將只返回第一個錯誤信息。

6. 特性標(biāo)簽

當(dāng)設(shè)計表單時,我們通常需要為每個表單域顯示一個標(biāo)簽。 標(biāo)簽告訴用戶他應(yīng)該在此表單域中填寫什么樣的信息。雖然我們可以在視圖中硬編碼一個標(biāo)簽, 但如果我們在相應(yīng)的模型中指定(標(biāo)簽),則會更加靈活方便。

默認(rèn)情況下 CModel 將簡單的返回特性的名字作為其標(biāo)簽。這可以通過覆蓋 attributeLabels() 方法自定義。 正如在接下來的小節(jié)中我們將看到的,在模型中指定標(biāo)簽會使我們能夠更快的創(chuàng)建出更強(qiáng)大的表單。

7. 創(chuàng)建動作 Action 方法

創(chuàng)建好 LoginForm 表單 Model 后,我們就可以為它編寫用戶提交后的處理代碼(對應(yīng)到 Controller 中的某個 Action 方法)。本例使用缺省的 SiteController,對應(yīng)的 action 為 actionLogin.

    public function actionLogin()
    {
        $model=new LoginForm;
        // collect user input data
        if(isset($_POST['LoginForm']))
        {
            $model->attributes=$_POST['LoginForm'];
            // validate user input and redirect to the previous page if valid
            if($model->validate() && $model->login()){

                $this->render('index');
                return;
            }

        }
        // display the login form
        $this->render('login',array('model'=>$model));
    }

如上所示,我們首先創(chuàng)建了一個 LoginForm 模型示例; 如果請求是一個 POST 請求(意味著這個登錄表單被提交了),我們則使用提交的數(shù)據(jù) $_POST[‘LoginForm’] 填充 $model ;然后我們驗證此輸入,如果驗證成功,則顯示 index 頁面。 如果驗證失敗,或者此動作被初次訪問,我們則渲染 login 視圖。 注意的我們修改了 SiteController 的缺省 action 為 login.

    /**
     * @var string sets the default action to be 'login'
     */
    public $defaultAction='login';

因此用戶見到的第一個頁面為 login 頁面而非 index 頁面,只有在用戶輸入正確的用戶名,本例使用固定的用戶名和密碼,參見 UserIdentity 類定義,實際應(yīng)用可以讀取數(shù)據(jù)庫或是 LDAP 服務(wù)器。

    /**
     * UserIdentity represents the data needed to identity a user.
     * It contains the authentication method that checks if the provided
     * data can identity the user.
     */
    class UserIdentity extends CUserIdentity
    {
        /**
         * Authenticates a user.
         * The example implementation makes sure if the username and password
         * are both 'demo'.
         * In practical applications, this should be changed to authenticate
         * against some persistent user identity storage (e.g. database).
         * @return boolean whether authentication succeeds.
         */
        public function authenticate()
        {
            $users=array(
                // username => password
                'demo'=>'demo',
                'admin'=>'admin',
            );
            if(!isset($users[$this->username]))
                $this->errorCode=self::ERROR_USERNAME_INVALID;
            else if($users[$this->username]!==$this->password)
                $this->errorCode=self::ERROR_PASSWORD_INVALID;
            else
                $this->errorCode=self::ERROR_NONE;
            return !$this->errorCode;
        }
    }

讓我們特別留意一下 login 動作中出現(xiàn)的下面的 PHP 語句:

    $model->attributes=$_POST['LoginForm'];

正如我們在安全的特性賦值中所講的, 這行代碼使用用戶提交的數(shù)據(jù)填充模型。 attributes 屬性由 CModel 定義,它接受一個名值對數(shù)組并將其中的每個值賦給相應(yīng)的模型特性。 因此如果 $_POST['LoginForm'] 給了我們這樣的一個數(shù)組,上面的那段代碼也就等同于下面冗長的這段 (假設(shè)數(shù)組中存在所有所需的特性):

    $model->username=$_POST['LoginForm']['username'];
    $model->password=$_POST['LoginForm']['password'];
    $model->rememberMe=$_POST['LoginForm']['rememberMe'];

8. 構(gòu)建視圖

編寫 login 視圖是很簡單的,我們以一個 form 標(biāo)記開始,它的 action 屬性應(yīng)該是前面講述的 login 動作的 URL。 然后我們需要為 LoginForm 類中聲明的屬性插入標(biāo)簽和表單域。最后, 我們插入一個可由用戶點(diǎn)擊提交此表單的提交按鈕。所有這些都可以用純HTML代碼完成。

Yii 提供了幾個助手(helper)類簡化視圖編寫。例如, 要創(chuàng)建一個文本輸入域,我們可以調(diào)用 CHtml::textField(); 要創(chuàng)建一個下拉列表,則調(diào)用 CHtml::dropDownList()

信息: 你可能想知道使用助手的好處,如果它們所需的代碼量和直接寫純 HTML 的代碼量相當(dāng)?shù)脑挕?答案就是助手可以提供比 HTML 代碼更多的功能。例如, 如下代碼將生成一個文本輸入域,它可以在用戶修改了其值時觸發(fā)表單提交動作。

    CHtml::textField($name,$value,array('submit'=>''));

不然的話你就需要寫一大堆 JavaScript 。

下面,我們使用 CHtml 創(chuàng)建一個登錄表單。我們假設(shè)變量 $model 是 LoginForm 的實例。

    <div class="form">
   <?php echo CHtml::beginForm(); ?>

        <?php echo CHtml::errorSummary($model); ?>

       <div class="row">
            <?php echo CHtml::activeLabel($model,'username'); ?>
            <?php echo CHtml::activeTextField($model,'username') ?>
        </div>

        <div class="row">
            <?php echo CHtml::activeLabel($model,'password'); ?>
            <?php echo CHtml::activePasswordField($model,'password') ?>
        </div>

        <div class="row rememberMe">
            <?php echo CHtml::activeCheckBox($model,'rememberMe'); ?>
            <?php echo CHtml::activeLabel($model,'rememberMe'); ?>
        </div>

        <div class="row submit">
            <?php echo CHtml::submitButton('Login'); ?>
        </div>

    <?php echo CHtml::endForm(); ?>
    </div><!-- form -->

上述代碼生成了一個更加動態(tài)的表單,例如, CHtml::activeLabel() 生成一個與指定模型的特性相關(guān)的標(biāo)簽。 如果此特性有一個輸入錯誤,此標(biāo)簽的 CSS class 將變?yōu)?error,通過 CSS 樣式改變了標(biāo)簽的外觀。 相似的,CHtml::activeTextField() 為指定模型的特性生成一個文本輸入域,并會在錯誤發(fā)生時改變它的 CSS class。

如果我們使用由 yiic 腳本生提供的 CSS 樣式文件,生成的表單就會像下面這樣:

http://wiki.jikexueyuan.com/project/yii-development-tutorial/images/8.1.jpg" alt="picture8.1" />

CSS 樣式定義在 css 目錄下,本例使用的為 Yii 缺省的樣式。

從版本 1.1.1 開始,提供了一個新的小物件 CActiveForm 以簡化表單創(chuàng)建。 這個小物件可同時提供客戶端及服務(wù)器端無縫的、一致的驗證。使用 CActiveForm, 上面的代碼可重寫為:

    <div class="form">
    <?php $form=$this->beginWidget('CActiveForm'); ?>

         <?php echo $form->errorSummary($model); ?>

        <div class="row">
            <?php echo $form->label($model,'username'); ?>
            <?php echo $form->textField($model,'username') ?>
        </div>

        <div class="row">
            <?php echo $form->label($model,'password'); ?>
            <?php echo $form->passwordField($model,'password') ?>
        </div>

        <div class="row rememberMe">
            <?php echo $form->checkBox($model,'rememberMe'); ?>
            <?php echo $form->label($model,'rememberMe'); ?>
        </div>

        <div class="row submit">
            <?php echo CHtml::submitButton('Login'); ?>
        </div>

    <?php $this->endWidget(); ?>
    </div><!-- form -->

本例下載。 從下篇開始將逐個介紹 Yii 框架支持的 UI 組件包括 CActiveForm 的用法。