創建動作
我們創建了模型之後,我們就需要寫一些邏輯代碼來操縱這個模型。我們把這部分的邏輯代碼放在控制器(controller)的動作(action)中。例如在用戶登錄過程中,我們編寫以下代碼:
public function actionLogin()
{
$model=new LoginForm;
if(isset($ POST['LoginForm']))
{
// collects user input data
$model->attributes=$ POST['LoginForm'];
// validates user input and redirect to previous page if validated
if($model->validate())
$this->redirect(Yii::app()->user->returnUrl);
}
// displays the login form
$this->render('login',array('model'=>$model));
}
在上面的代碼中,我們首先創建一個模型LoginForm的實例,如果請求是_POST(表明login form已經提交),然後我們用 $ POST['LoginForm']的表單數據來給這個實例賦值,然後再對這些數據進行校驗,如果校驗通過了,就重定向到之前的用戶界面,如果失敗了,就回到用戶登錄的界面(這時的用戶界面跟之前就不一樣了,有錯誤提示啊)
在上面的這些代碼中,讓我們來重點關注一下這句:
$model->attributes=$ POST['LoginForm'];
在之前的安全設置屬性章節中,我們提到過這個是用終端用戶提交的數據來給模型實例進行集體賦值的。這些屬性的特點是在CModel中定義的,採用一組name-values的參數來進行賦值。所以如果$ POST['LoginForm']給我們一個數組,上面的這行代碼就等同於:
$model->username=$ POST['LoginForm']['username'];
$model->password=$ POST['LoginForm']['password'];
$model->rememberMe=$ POST['LoginForm']['rememberMe'];
創建窗體
寫登錄的表單相對來說就很簡單了。我們先從form這表標籤開始,他的動作屬性就是之前我們提到過的登錄動作的URL。然後我們插入一些登錄用到的標籤,以及輸入框。最後,我們放置一個提交按鈕。所有這些工作都可以用純的HTML語句來實現。
Yii,我們偉大的Yii框架,提供了一些幫助類來簡化這些編碼工作。例如,我們要插入一個文本輸入框,就可以調用CHtml::textField();想弄一個下拉框,就可以調用CHtml::dropDownList().
有些人可能會問了,我們這麼做,跟直接用html比起來,有什麼好處呢?答案是這些幫助類,不僅可以提供html代碼,還可以做更多的事情。例如,以下的代碼在用戶改變輸入框的內容時,會觸發提交動作:
CHtml::textField($name,$value,array('submit'=>''));
如果不這樣的話,我們必須寫一大堆的JS來實現這個功能了。
下面,我們來看一個實例,用CHtml創建登錄表單。我們假設$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 -->
上例中代碼生成的是一個動態的表單。例如,CHtml::activeLabel()生成的標籤是關聯模型中的特定屬性的。如果這個屬性的輸入有誤,標籤的CSS樣式就會跳到錯誤提示的樣式。同樣的,CHtml::activeTextField生成的文本輸入框,當有錯誤輸入時,也會提示相應的錯誤信息。
從Yii的1.1.1版本開始,一個新的工具CActiveForm用來簡化表單的創建工作。這個工具可以用來實現客戶端與服務器之間的無縫校驗!強大!如果用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 -->
採集表格化輸入數據
有時候,我批量的採集用戶的輸入信息。例如,用戶可以同時輸入有關很多個模型的數據內容,然後依次提交。我們稱之爲表格化數據輸入,因爲這些輸入框一般都是在html的table標籤裏。
在使用表格化輸入之前,我們要先創建或者填充一組模型的對象,是新建還是填充,取決於我們是插入數據或者是更新數據來着。 然後我們從用戶輸入的數據中,給各模型對象的屬性賦值。與單一模型對象比起來,差別在於我們賦值是用$ POST['ModelClass'][$i], 而非之前的$ POST['ModelClass'].
public function actionBatchUpdate()
{
// retrieve items to be updated in a batch mode
// assuming each item is of model class 'Item'
$items=$this->getItemsToUpdate();
if(isset($ POST['Item']))
{
$valid=true;
foreach($items as $i=>$item)
{
if(isset($ POST['Item'][$i]))
$item->attributes=$ POST['Item'][$i];
$valid=$item->validate() && $valid;
}
if($valid) // all items are valid
// ...do something here
}
// displays the view to collect tabular input
$this->render('batchUpdate',array('items'=>$items));
}
在這個動作準備好以後,我們要在batchUpdate這個視圖裏,呈現HTML的輸入表格。
<div class="form">
<?php echo CHtml::beginForm(); ?>
<table>
<tr><th>Name</th><th>Price</th><th>Count</th><th>Description</th></tr>
<?php foreach($items as $i=>$item): ?>
<tr>
<td><?php echo CHtml::activeTextField($item,"[$i]name"); ?></td>
<td><?php echo CHtml::activeTextField($item,"[$i]price"); ?></td>
<td><?php echo CHtml::activeTextField($item,"[$i]count"); ?></td>
<td><?php echo CHtml::activeTextArea($item,"[$i]description"); ?></td>
</tr>
<?php endforeach; ?>
</table>
<?php echo CHtml::submitButton('Save'); ?>
<?php echo CHtml::endForm(); ?>
</div><!-- form -->
注意,在上面的代碼中,用"[$i]name"而不是"name"作爲CHtml::activeTextArea的第二個參數。(以上這個例子,雖然是批量賦值沒錯,但是還是單一的模型的多對象而已啊)
如果校驗器檢測有任何錯誤,當前的輸入框就會自動高亮,就像之前提到過的錯誤提示。