表單(Form)的使用(1)

翻了兩篇,突然想起來,忘了提個醒。各位看官,我所翻的這個yii 指引手冊早有中文版的,可以去找來看看。本人是閒來無聊,自己翻。

        對於一個web工程來說,最主要的工作就是通過HTML表單來蒐集用戶的輸入數據。除了設計表單,程序員還需要設置已有數據或者是默認值,驗證用戶輸入,正確並人性化的輸出錯誤提示信息,保存數據到存儲設備。Yii通過MVC架構,非常輕鬆的完成以上所述的工作流。

        以下是用Yii處理form時的經典步驟:

        1、爲要蒐集的數據創建一個模型。

        2、創建一個控制器的動作,用來相應表單提交信息。

        3、在視圖文件中,創建一個表單,用來關聯控制器的動作。

        接下來,我們詳細的描述以上的每個步驟。

1、創建模型

        在寫表單的HTML代碼前,我們先要弄明白的一點:我們希望終端用戶提供什麼樣的數據,以及這些數據必須符合什麼規則。模型類就可以用來記錄這些信息的,他就是用來保存用戶輸入信息,並且驗證信息的。

        基於我們想讓用戶以何種方式輸入,我們可以創建兩種類型的模型。如果用戶數據採集使用之後,是要丟棄的,那麼我們就可以創建一個form model;如果用戶數據採集之後是要保存到數據庫的,我們就創建一個active record。這兩種模型都是繼承於相同的基類CModel的,這個基類定義了一些表單常用的接口。

1.1 定義模型類

        下面我們創建一個LoginForm的模型類來採集用戶在登錄時的信息。因爲用戶登錄只是驗證用戶信息,不需要保存,所以採用form model。(本人認爲,實際應用中,用戶登錄信息除了校驗用戶的信息,一般都還是需要記錄一些信息的,具體依不同項目而定)

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

}

以上的代碼,聲明瞭LoginForm的3個屬性:$username, $password and $rememberMe. 具體幹嘛用的不需要翻譯了,一目瞭然。這些屬性就是用來保存用戶輸入的數據或者是數據庫的數據。

1.2 聲明驗證規則

        一旦用戶提交了數據,模型獲取到了輸入信息,我們要驗證這些輸入的合法性。這個工作是由一堆的規則來驗證輸入的信息。我們在方法rules()中來配置這一些驗證規則。

class LoginForm extends CFormModel
{
        public $username;
        public $password;
        public $rememberMe=false;
        private $ identity;3.2CreatingModel55
        public function rules()
        {
                return array(
                        array('username,password', 'required'), //表明用戶名,密碼是必填項
                        array('rememberMe', 'boolean'),//布爾型
                        array('password', 'authenticate'),//需到authenticate驗證
                );
        }
        public function authenticate($attribute,$params)
        {
                $this-> identity=new UserIdentity($this->username,$this->password);
                if(!$this-> identity->authenticate())
                $this->addError('password','Incorrectusernameorpassword.');
        }
}

        所有的規則,都必須符合以下的格式:

        array('AttributeList', 'Validator', 'on'=>'ScenarioList',...additional options)

        AttributeList:需要用這條規則來校驗的屬性列表,如果是多個屬性,中間用, 隔開。

        Validator:驗證器。也就是指定的這些屬性列表,需要用哪個校驗器來檢驗。

        on:可選項,用來指明在什麼場景需要啓用該規則。

        有三種方式來選擇規則中的驗證器。首先,驗證器可以是自身模型類的一個方法,如上例中的authenticate。驗證器必須符合以下格式:public function ValidatorName($attribute,$params) {...}。第二,這個驗證器可以是某個驗證器類的類名稱。當規則啓用的時候,這個驗證器類就會創建一個實例並運行起來,執行他的驗證功能。規則中的addtional options就是用來初始化這個實例屬性的。第三,這個驗證器也可以是某個驗證器的別名。上例的規則中,'required'就是CRequiredValidator的別名,用來校驗所有的屬性值不爲空。以下列出一份完整的別名名單,能背下來最後,目前我是還沒背下來:

       boolean, captcha, email, date, default, exist, file, filter, in, length, match, numerical, required, type, unique, url

        樣例示範:

        // username is required
        array('username', 'required'),
        // username must be between 3 and 12 characters
        array('username', 'length', 'min'=>3, 'max'=>12),
        // when in register scenario, password must match password2
        array('password', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'),
        // when in login scenario, password must be authenticated
        array('password', 'authenticate', 'on'=>'login'),

1.3 安全的給屬性賦值

        在模型實例化以後,我們通常都需要由終端用戶來填充數據。可以簡單的由以下代碼實現集體賦值(massive assignment):

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

上例中的最後一行就是集體賦值,把從$_POST['LoginFom']的數據賦值到相對應的模型屬性中。作用等同於:

        foreach($ POST['LoginForm'] as $name=>$value)
        {
                if($name is a safe attribute)
                $model->$name=$value;
        }

他的關鍵之處在於指定哪些屬性是安全的。假設我們把某個表的主鍵設置爲安全類型,那麼當***有機會修改該記錄的主鍵值,並篡改數據,這些都是不合法的。

聲明安全的屬性

一個屬性,如果在給定的場景下,符合驗證規則,那麼我們就認爲這個屬性是安全的。例如

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

在login, register的時候,用戶名,密碼是必填項,在register的時候,用戶名,密碼,email都是必填項。

所以,在用戶登錄的時候,只有用戶名,密碼這兩個屬性會被集體賦值(massive assignment), 因爲在登錄的時候,規則只有這兩個屬性;同樣的,在註冊新用戶的時候,以上的三個屬性都會被集體賦值。

// in login scenario
$model=new User('login');
if(isset($ POST['User']))
        $model->attributes=$ POST['User'];
// in register scenario
$model=new User('register');
if(isset($ POST['User']))
        $model->attributes=$ POST['User'];

好了,現在的問題,我們爲什麼要用這樣的策略來決定一個屬性是否是安全的呢?想想看,如果一個屬性,已經被一條或者是N條的驗證規則驗證過了,那麼我們還有什麼好擔心的呢?

必須謹記的一點,驗證規則主要是用來驗證用戶的提交數據,而不是代碼所生成的數據(例如時間戳,自動生成的主鍵ID)。所以,千萬記住,不要爲那些不是從終端用戶提交的數據進行規則校驗。  

有時候,我們想把某些屬性設置爲安全屬性,即使我們並沒有規則來校驗他。例如一篇文章的內容,可以允許任何的內容輸入。這時候我們就可以使用安全規則,來強制說明這個屬性是安全的:

array('content', 'safe')

有強制說明安全,那就會有強制說明不安全的了:

array('permission', 'unsafe')

這個被註明爲不安全的屬性有什麼用呢?他很有用,是之前所提到的安全屬性的一個例外。

對於這些不安全的屬性,我們必須親自一一爲他們賦值,例如:

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

1.4 觸發式校驗

一個模型在用戶提交數據之後,我們可以調用CModel::validate()的方法來觸發數據校驗的線程。這個方法返回一個校驗的結果,通過或者不通過。對於CActiveRecord的模型來說,在我們調用CActiveRecord::save()的時候,也會自動觸發該方法。

我們可以設置一個場景的屬性,以及一些驗證規則來校驗。

校驗器是在一個基礎的場景使用的,這個場景的屬性確定了場景是用哪個模型,以及那些校驗規則會被啓用。例如,在用戶登錄(Login)的時候,我們只想校驗用戶名,密碼;在註冊新用戶的場景時,我們需要驗證更多的信息,例如emai,地址等。

// creates a User model in register scenario. It is equivalent to:
// $model=new User;
// $model->scenario='register';
        $model=new User('register');
// populates the input values into the model
        $model->attributes=$ POST['User'];
// performs the validation
        if($model->validate()) // if the inputs are valid
                ...
        else
                ...

在該場景中,規則是否適用取決於規則中的"on”選項。如果規則的on選項沒有被設置,則意味着該規則適用於所有場景。例如:

public function rules()
{

        return array(
                array('username, password', 'required'),
                array('password repeat', 'required', 'on'=>'register'),
                array('password', 'compare', 'on'=>'register'),
        );
}

第一條規則適用於任何場景,而第二條規則只有在regster的場景時適用。

1.5 捕獲校驗器錯誤

在驗證完成之後,任何錯誤都可能存在於模型的對象中。怎麼才能獲取這些錯誤信息呢?我們可以通過調用CModel::getErrors() 以及CModel::getError()。這兩個的區別在於第一個方法會返回校驗後所有的錯誤信息,而後者只返回第一個錯誤。

1.6 屬性標籤

在設計的時候,我們通常需要爲要輸入的屬性設置一個標籤,用來告訴終端用戶,輸入的是什麼項目。當然,最原始的方法,我們可以自己在視圖裏用代碼編寫一個標籤,但是,有更好的方法了。最好是在當前的模型中,提供一個標籤,這樣既方便又容易維護。

默認情況下,CModel只是簡單的用該屬性的名稱來作爲標籤。這可以通過重載attributeLabels()這個方法來設置。在後續的章節中,我們會看到在模型中設置標籤,會使我們的開發更快速,也更健壯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章