使用表單
本章節介紹如何創建一個讓用戶提交數據的表單頁。該頁將顯示一個包含 name 輸入框和 email 輸入框的表單。當提交這兩部分信息後,頁面將會顯示用戶所輸入的信息。
爲了實現這個目標,除了創建一個操作和兩個視圖外,還需要創建一個模型。
貫穿整個小節,你將會學到:
創建模型
模型類 EntryForm
代表從用戶那請求的數據,該類如下所示並存儲在 models/EntryForm.php
文件中。請參考類自動加載章節獲取更多關於類命名約定的介紹。
<?php
namespace app\models;
use yii\base\Model;
class EntryForm extends Model
{
public $name;
public $email;
public function rules()
{
return [
[['name', 'email'], 'required'],
['email', 'email'],
];
}
}
該類繼承自Yii 提供的一個基類 yii\base\Model,該基類通常用來表示數據。
補充:yii\base\Model 被用於普通模型類的父類並與數據表無關。yii\db\ActiveRecord 通常是普通模型類的父類但與數據表有關聯(譯註:yii\db\ActiveRecord 類其實也是繼承自 yii\base\Model,增加了數據庫處理)。
EntryForm
類包含 name
和 email
兩個公共成員,用來儲存用戶輸入的數據。它還包含一個名爲 rules()
的方法,用來返回數據驗證規則的集合。上面聲明的驗證規則表示:
name
和email
值都是必須的email
的值必須滿足email規則驗證
如果你有一個處理用戶提交數據的 EntryForm
對象,你可以調用它的 yii\base\Model::validate() 方法觸發數據驗證。如果有數據驗證失敗,將把 yii\base\Model::hasErrors
屬性設爲 ture,想要知道具體發生什麼錯誤就調用 yii\base\Model::getErrors。
<?php
$model = new EntryForm();
$model->name = 'Qiang';
$model->email = 'bad';
if ($model->validate()) {
// 驗證成功!
} else {
// 失敗!
// 使用 $model->getErrors() 獲取錯誤詳情
}
創建操作
下面你得在 site
控制器中創建一個 entry
操作用於新建的模型。操作的創建和使用已經在說一聲你好小節中解釋了。
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\EntryForm;
class SiteController extends Controller
{
// ...其它代碼...
public function actionEntry()
{
$model = new EntryForm;
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
// 驗證 $model 收到的數據
// 做些有意義的事 ...
return $this->render('entry-confirm', ['model' => $model]);
} else {
// 無論是初始化顯示還是數據驗證錯誤
return $this->render('entry', ['model' => $model]);
}
}
}
該操作首先創建了一個 EntryForm
對象。然後嘗試從 $_POST
蒐集用戶提交的數據,由
Yii 的 yii\web\Request::post() 方法負責蒐集。如果模型被成功填充數據(也就是說用戶已經提交了 HTML 表單),操作將調用 yii\base\Model::validate() 去確保用戶提交的是有效數據。
補充:表達式
Yii::$app
代表應用實例,它是一個全局可訪問的單例。同時它也是一個服務定位器,能提供request
,response
,db
等等特定功能的組件。在上面的代碼裏就是使用request
組件來訪問應用實例收到的$_POST
數據。
用戶提交表單後,操作將會渲染一個名爲 entry-confirm
的視圖去確認用戶輸入的數據。如果沒填表單就提交,或數據包含錯誤(譯者:如 email 格式不對),entry
視圖將會渲染輸出,連同表單一起輸出的還有驗證錯誤的詳細信息。
注意:在這個簡單例子裏我們只是呈現了有效數據的確認頁面。實踐中你應該考慮使用 yii\web\Controller::refresh() 或 yii\web\Controller::redirect() 去避免表單重複提交問題。
創建視圖
最後創建兩個視圖文件 entry-confirm
和 entry
。他們會被剛纔創建的 entry
操作渲染。
entry-confirm
視圖簡單地顯示提交的 name 和 email 數據。視圖文件保存在 views/site/entry-confirm.php
。
<?php
use yii\helpers\Html;
?>
<p>You have entered the following information:</p>
<ul>
<li><label>Name</label>: <?= Html::encode($model->name) ?></li>
<li><label>Email</label>: <?= Html::encode($model->email) ?></li>
</ul>
entry
視圖顯示一個 HTML 表單。視圖文件保存在 views/site/entry.php
。
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'name') ?>
<?= $form->field($model, 'email') ?>
<div class="form-group">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
視圖使用了一個功能強大的小部件 yii\widgets\ActiveForm 去生成 HTML 表單。其中的 begin()
和 end()
分別用來渲染表單的開始和關閉標籤。在這兩個方法之間使用了
yii\widgets\ActiveForm::field() 方法去創建輸入框。第一個輸入框用於 “name”,第二個輸入框用於 “email”。之後使用 yii\helpers\Html::submitButton() 方法生成提交按鈕。
嘗試下
用瀏覽器訪問下面的 URL 看它能否工作:
http://hostname/index.php?r=site/entry
你會看到一個包含兩個輸入框的表單的頁面。每個輸入框的前面都有一個標籤指明應該輸入的數據類型。如果什麼都不填就點擊提交按鈕,或填入格式不正確的 email 地址,將會看到在對應的輸入框下顯示錯誤信息。
輸入有效的 name 和 email 信息並提交後,將會看到一個顯示你所提交數據的確認頁面。
效果說明
你可能會好奇 HTML 表單暗地裏是如何工作的呢,看起來它可以爲每個輸入框顯示文字標籤,而當你沒輸入正確的信息時又不需要刷新頁面就能給出錯誤提示,似乎有些神奇。
是的,其實數據首先由客戶端 JavaScript 腳本驗證,然後纔會提交給服務器通過 PHP 驗證。yii\widgets\ActiveForm 足夠智能到把你在 EntryForm
模型中聲明的驗證規則轉化成客戶端
JavaScript 腳本去執行驗證。如果用戶瀏覽器禁用了 JavaScript, 服務器端仍然會像 actionEntry()
方法裏這樣驗證一遍數據。這保證了任何情況下用戶提交的數據都是有效的。
警告:客戶端驗證是提高用戶體驗的手段。無論它是否正常啓用,服務端驗證則都是必須的,請不要忽略它。
輸入框的文字標籤是 field()
方法生成的,內容就是模型中該數據的屬性名。例如模型中的 name
屬性生成的標籤就是 Name
。
你可以在視圖中自定義標籤:
<?= $form->field($model, 'name')->label('自定義 Name') ?>
<?= $form->field($model, 'email')->label('自定義 Email') ?>
補充:Yii 提供了相當多類似的小部件去幫你生成複雜且動態的視圖。在後面你還會瞭解到自己寫小部件是多麼簡單。你可能會把自己的很多視圖代碼轉化成小部件以提高重用,加快開發效率。