# 表單(Forms)
Phalcon中提供了`Phalcon\Forms`組件以方便開發者創建和維護應用中的表單。
下面的例子中展示了基本的使用方法:
~~~
<?php
use Phalcon\Forms\Form;
use Phalcon\Forms\Element\Text;
use Phalcon\Forms\Element\Select;
$form = new Form();
$form->add(
new Text(
"name"
)
);
$form->add(
new Text(
"telephone"
)
);
$form->add(
new Select(
"telephoneType",
[
"H" => "Home",
"C" => "Cell",
]
)
);
~~~
可在表單定義時穿插使用表單元素的字義:
~~~
<h1>
Contacts
</h1>
<form method="post">
<p>
<label>
Name
</label>
<?php echo $form->render("name"); ?>
</p>
<p>
<label>
Telephone
</label>
<?php echo $form->render("telephone"); ?>
</p>
<p>
<label>
Type
</label>
<?php echo $form->render("telephoneType"); ?>
</p>
<p>
<input type="submit" value="Save" />
</p>
</form>
~~~
開發者可根據需要渲染HTML組件。 當使用:code:render()`函數時, phalcon內部會使用 :doc:`Phalcon\\Tag 生成相應的html項, 第二個參數中可以對一些屬性進行設置。
~~~
<p>
<label>
Name
</label>
<?php echo $form->render("name", ["maxlength" => 30, "placeholder" => "Type your name"]); ?>
</p>
~~~
HTML的屬性也可以在創建時指定:
~~~
<?php
$form->add(
new Text(
"name",
[
"maxlength" => 30,
"placeholder" => "Type your name",
]
)
);
~~~
## 初始化表單(Initializing forms)
從上面的例子我們可以看到表單項也可以在form對象初始化后進行添加。 當然開發者也可以對原有的Form類進行擴展:
~~~
<?php
use Phalcon\Forms\Form;
use Phalcon\Forms\Element\Text;
use Phalcon\Forms\Element\Select;
class ContactForm extends Form
{
public function initialize()
{
$this->add(
new Text(
"name"
)
);
$this->add(
new Text(
"telephone"
)
);
$this->add(
new Select(
"telephoneType",
TelephoneTypes::find(),
[
"using" => [
"id",
"name",
]
]
)
);
}
}
~~~
由于[Phalcon\\Forms\\Form](http://docs.iphalcon.cn/api/Phalcon_Forms_Form.html)實現了[Phalcon\\Di\\Injectable](http://docs.iphalcon.cn/api/Phalcon_Di_Injectable.html)接口, 所以開發者可以根據自己的需要訪問應用中的服務。
~~~
<?php
use Phalcon\Forms\Form;
use Phalcon\Forms\Element\Text;
use Phalcon\Forms\Element\Hidden;
class ContactForm extends Form
{
/**
* This method returns the default value for field 'csrf'
*/
public function getCsrf()
{
return $this->security->getToken();
}
public function initialize()
{
// Set the same form as entity
$this->setEntity($this);
// Add a text element to capture the 'email'
$this->add(
new Text(
"email"
)
);
// Add a text element to put a hidden CSRF
$this->add(
new Hidden(
"csrf"
)
);
}
}
~~~
相關的實體在初始化時添加到表單, 自定義的選項通過構造器傳送:
~~~
<?php
use Phalcon\Forms\Form;
use Phalcon\Forms\Element\Text;
use Phalcon\Forms\Element\Hidden;
class UsersForm extends Form
{
/**
* Forms initializer
*
* @param Users $user
* @param array $options
*/
public function initialize(Users $user, array $options)
{
if ($options["edit"]) {
$this->add(
new Hidden(
"id"
)
);
} else {
$this->add(
new Text(
"id"
)
);
}
$this->add(
new Text(
"name"
)
);
}
}
~~~
在表單實例中必須要這樣使用:
~~~
<?php
$form = new UsersForm(
new Users(),
[
"edit" => true,
]
);
~~~
## 驗證(Validation)
Phalcon表單組件可以和[validation](http://docs.iphalcon.cn/reference/validation.html)集成,以提供驗證。 開發者要單獨為每個html元素提供內置或自定義的驗證器。
~~~
<?php
use Phalcon\Forms\Element\Text;
use Phalcon\Validation\Validator\PresenceOf;
use Phalcon\Validation\Validator\StringLength;
$name = new Text(
"name"
);
$name->addValidator(
new PresenceOf(
[
"message" => "The name is required",
]
)
);
$name->addValidator(
new StringLength(
[
"min" => 10,
"messageMinimum" => "The name is too short",
]
)
);
$form->add($name);
~~~
然后, 開發者可以根據用戶的輸入進行驗證:
~~~
<?php
if (!$form->isValid($_POST)) {
$messages = $form->getMessages();
foreach ($messages as $message) {
echo $message, "<br>";
}
}
~~~
驗證器執行的順序和注冊的順序一致。
默認情況下,所有的元素產生的消息是放在一起的, 所以開發者可以使用簡單的foreach來遍歷消息, 開發者可以按照自己的意愿組織輸出:
~~~
<?php
foreach ($form->getMessages(false) as $attribute => $messages) {
echo "Messages generated by ", $attribute, ":", "\n";
foreach ($messages as $message) {
echo $message, "<br>";
}
}
~~~
或獲取指定元素的消息:
~~~
<?php
$messages = $form->getMessagesFor("name");
foreach ($messages as $message) {
echo $message, "<br>";
}
~~~
## 過濾(Filtering)
表單元素可以在進行驗證前先進行過濾, 開發者可以為每個元素設置過濾器:
~~~
<?php
use Phalcon\Forms\Element\Text;
$name = new Text(
"name"
);
// Set multiple filters
$name->setFilters(
[
"string",
"trim",
]
);
$form->add($name);
$email = new Text(
"email"
);
// Set one filter
$email->setFilters(
"email"
);
$form->add($email);
~~~
> Learn more about filtering in Phalcon by reading the[Filter documentation](http://docs.iphalcon.cn/reference/filter.html).
## 表單與實體(Forms + Entities)
我們可以把 model/collection/plain 設置到表單對象中, 這樣 phalcon 會自動的設置表單元素的值:
~~~
<?php
$robot = Robots::findFirst();
$form = new Form($robot);
$form->add(
new Text(
"name"
)
);
$form->add(
new Text(
"year"
)
);
~~~
在表單渲染時如果表單項未設置默認值, phalcon會使用對象實體值作為默認值:
~~~
<?php echo $form->render("name"); ?>
~~~
開發者可以使用下面的方式驗證表單及利用用戶的輸入來設置值:
~~~
<?php
$form->bind($_POST, $robot);
// Check if the form is valid
if ($form->isValid()) {
// Save the entity
$robot->save();
}
~~~
也可以使用一個簡單的類做為對象實體進行參數傳遞:
~~~
<?php
class Preferences
{
public $timezone = "Europe/Amsterdam";
public $receiveEmails = "No";
}
~~~
使用此類做為對象實體,這樣可以使用此類中的值作為表單的默認值:
~~~
<?php
$form = new Form(
new Preferences()
);
$form->add(
new Select(
"timezone",
[
"America/New_York" => "New York",
"Europe/Amsterdam" => "Amsterdam",
"America/Sao_Paulo" => "Sao Paulo",
"Asia/Tokyo" => "Tokyo",
]
)
);
$form->add(
new Select(
"receiveEmails",
[
"Yes" => "Yes, please!",
"No" => "No, thanks",
]
)
);
~~~
實體中也可以使用getters, 這樣可以給開發者更多的自由, 當然也會使開發稍麻煩一些,不過這是值得的:
~~~
<?php
class Preferences
{
public $timezone;
public $receiveEmails;
public function getTimezone()
{
return "Europe/Amsterdam";
}
public function getReceiveEmails()
{
return "No";
}
}
~~~
## 表單控件(Form Elements)
Phalcon提供了一些內置的html元素類, 所有這些元素類僅位于[Phalcon\\Forms\\Element](http://docs.iphalcon.cn/api/Phalcon_Forms_Element.html)命名空間下:
| 名稱 | 描述 |
| --- | --- |
| [Phalcon\\Forms\\Element\\Text](http://docs.iphalcon.cn/api/Phalcon_Forms_Element_Text.html) | 產生 INPUT\[type=text\] 項 |
| [Phalcon\\Forms\\Element\\Password](http://docs.iphalcon.cn/api/Phalcon_Forms_Element_Password.html) | 產生 INPUT\[type=password\] 項 |
| [Phalcon\\Forms\\Element\\Select](http://docs.iphalcon.cn/api/Phalcon_Forms_Element_Select.html) | 產生 SELECT tag (combo lists) 項 |
| [Phalcon\\Forms\\Element\\Check](http://docs.iphalcon.cn/api/Phalcon_Forms_Element_Check.html) | 產生 INPUT\[type=check\] 項 |
| [Phalcon\\Forms\\Element\\TextArea](http://docs.iphalcon.cn/api/Phalcon_Forms_Element_TextArea.html) | 產生 TEXTAREA 項 |
| [Phalcon\\Forms\\Element\\Hidden](http://docs.iphalcon.cn/api/Phalcon_Forms_Element_Hidden.html) | 產生 INPUT\[type=hidden\] 項 |
| [Phalcon\\Forms\\Element\\File](http://docs.iphalcon.cn/api/Phalcon_Forms_Element_File.html) | 產生 INPUT\[type=file\] 項 |
| [Phalcon\\Forms\\Element\\Date](http://docs.iphalcon.cn/api/Phalcon_Forms_Element_Date.html) | 產生 INPUT\[type=date\] 項 |
| [Phalcon\\Forms\\Element\\Numeric](http://docs.iphalcon.cn/api/Phalcon_Forms_Element_Numeric.html) | 產生 INPUT\[type=number\] 項 |
| [Phalcon\\Forms\\Element\\Submit](http://docs.iphalcon.cn/api/Phalcon_Forms_Element_Submit.html) | 產生 INPUT\[type=submit\] 項 |
## 事件回調(Event Callbacks)
當擴展表單時, 我們可以在表單類中實現驗證前操作及驗證后操作:
~~~
<?php
use Phalcon\Forms\Form;
class ContactForm extends Form
{
public function beforeValidation()
{
}
}
~~~
## 渲染表單(Rendering Forms)
開發者對表單的渲染操作有完全的控制, 下面的的例子展示了如何使用標準方法渲染html元素:
~~~
<?php
<form method="post">
<?php
// Traverse the form
foreach ($form as $element) {
// Get any generated messages for the current element
$messages = $form->getMessagesFor(
$element->getName()
);
if (count($messages)) {
// Print each element
echo '<div class="messages">';
foreach ($messages as $message) {
echo $message;
}
echo "</div>";
}
echo "<p>";
echo '<label for="', $element->getName(), '">', $element->getLabel(), "</label>";
echo $element;
echo "</p>";
}
?>
<input type="submit" value="Send" />
</form>
~~~
或是在登錄表單中重用表單類:
~~~
<?php
use Phalcon\Forms\Form;
class ContactForm extends Form
{
public function initialize()
{
// ...
}
public function renderDecorated($name)
{
$element = $this->get($name);
// Get any generated messages for the current element
$messages = $this->getMessagesFor(
$element->getName()
);
if (count($messages)) {
// Print each element
echo '<div class="messages">';
foreach ($messages as $message) {
echo $this->flash->error($message);
}
echo "</div>";
}
echo "<p>";
echo '<label for="', $element->getName(), '">', $element->getLabel(), "</label>";
echo $element;
echo "</p>";
}
}
~~~
視圖中:
~~~
<?php
echo $element->renderDecorated("name");
echo $element->renderDecorated("telephone");
~~~
## 創建表單控件(Creating Form Elements)
除了可以使用phalcon提供的html元素以外, 開發者還可以使用自定義的html元素:
~~~
<?php
use Phalcon\Forms\Element;
class MyElement extends Element
{
public function render($attributes = null)
{
$html = // ... Produce some HTML
return $html;
}
}
~~~
## 表單管理(Forms Manager)
此組件為開發者提供了一個表單管理器, 可以用來注冊表單,此組件可以使用服務容器來訪問:
~~~
<?php
use Phalcon\Forms\Manager as FormsManager;
$di["forms"] = function () {
return new FormsManager();
};
~~~
表單被添加到表單管理器, 然后設置了唯一的名字:
~~~
<?php
$this->forms->set(
"login",
new LoginForm()
);
~~~
使用唯一名, 我們可以在應用的任何地方訪問到表單:
~~~
<?php
$loginForm = $this->forms->get("login");
echo $loginForm->render();
~~~
## 外部資源(External Resources)
* [V?kuró](http://vokuro.phalconphp.com/)是一個使用表單構建器來創建和維護表單的示例 \[[Github](https://github.com/phalcon/vokuro)\]
- 簡介
- 安裝
- 安裝(installlation)
- XAMPP下的安裝
- WAMP下安裝
- Nginx安裝說明
- Apache安裝說明
- Cherokee 安裝說明
- 使用 PHP 內置 web 服務器
- Phalcon 開發工具
- Linux 系統下使用 Phalcon 開發工具
- Mac OS X 系統下使用 Phalcon 開發工具
- Windows 系統下使用 Phalcon 開發工具
- 教程
- 教程 1:讓我們通過例子來學習
- 教程 2:INVO簡介
- 教程 3: 保護INVO
- 教程4: 使用CRUD
- 教程5: 定制INVO
- 教程 6: V?kuró
- 教程 7:創建簡單的 REST API
- 組件
- 依賴注入與服務定位器
- MVC架構
- 使用控制器
- 使用模型
- 模型關系
- 事件與事件管理器
- Behaviors
- 模型元數據
- 事務管理
- 驗證數據完整性
- Workingwith Models
- Phalcon查詢語言
- 緩存對象關系映射
- 對象文檔映射 ODM
- 使用視圖
- 視圖助手
- 資源文件管理
- Volt 模版引擎
- MVC 應用
- 路由
- 調度控制器
- Micro Applications
- 使用命名空間
- 事件管理器
- Request Environmen
- 返回響應
- Cookie 管理
- 生成 URL 和 路徑
- 閃存消息
- 使用 Session 存儲數據
- 過濾與清理
- 上下文編碼
- 驗證Validation
- 表單_Forms
- 讀取配置
- 分頁 Pagination
- 使用緩存提高性能
- 安全
- 加密與解密 Encryption/Decryption
- 訪問控制列表
- 多語言支持
- 類加載器 Class Autoloader
- 日志記錄_Logging
- 注釋解析器 Annotations Parser
- 命令行應用 Command Line Applications
- Images
- 隊列 Queueing
- 數據庫抽象層
- 國際化
- 數據庫遷移
- 調試應用程序
- 單元測試
- 進階技巧與延伸閱讀
- 提高性能:下一步該做什么?
- Dependency Injection Explained
- Understanding How Phalcon Applications Work
- Api
- Abstract class Phalcon\Acl