表单(Forms)

Phalcon中提供了 Phalcon\Forms 组件以方便开发者创建和维护应用中的表单。

下面的例子中展示了基本的使用方法:

  1. <?php
  2.  
  3. use Phalcon\Forms\Form;
  4. use Phalcon\Forms\Element\Text;
  5. use Phalcon\Forms\Element\Select;
  6.  
  7. $form = new Form();
  8.  
  9. $form->add(new Text("name"));
  10.  
  11. $form->add(new Text("telephone"));
  12.  
  13. $form->add(
  14. new Select(
  15. "telephoneType",
  16. array(
  17. 'H' => 'Home',
  18. 'C' => 'Cell'
  19. )
  20. )
  21. );

可在表单定义时穿插使用表单元素的字义:

  1. <h1>Contacts</h1>
  2.  
  3. <form method="post">
  4.  
  5. <p>
  6. <label>Name</label>
  7. <?php echo $form->render("name"); ?>
  8. </p>
  9.  
  10. <p>
  11. <label>Telephone</label>
  12. <?php echo $form->render("telephone"); ?>
  13. </p>
  14.  
  15. <p>
  16. <label>Type</label>
  17. <?php echo $form->render("telephoneType"); ?>
  18. </p>
  19.  
  20. <p>
  21. <input type="submit" value="Save" />
  22. </p>
  23.  
  24. </form>

开发者可根据需要渲染HTML组件。 当使用render()函数时, phalcon内部会使用 Phalcon\Tag 生成相应的html项,第二个参数中可以对一些属性进行设置。

  1. <p>
  2. <label>Name</label>
  3. <?php echo $form->render("name", array('maxlength' => 30, 'placeholder' => 'Type your name')); ?>
  4. </p>

HTML的属性也可以在创建时指定:

  1. <?php
  2.  
  3. $form->add(
  4. new Text(
  5. "name",
  6. array(
  7. 'maxlength' => 30,
  8. 'placeholder' => 'Type your name'
  9. )
  10. )
  11. );

表单元素(Forms Elements)

所有 Phalcon\Tag 支持的 HTML 元素,都可以作为表单元素来使用。例如,Phalcon 内置不存在 PhalconFormsElementTel 元素类,但 Phalcon\Tag 中存在 tel 方法,我们仍然可以用下面的方式创建表单元素:

  1. <?php
  2.  
  3. $element = new Phalcon\Forms\Element('mytel', NULL, NULL, NULL, 'tel');

构造函数的第一个参数是元素名称(name),第二个参数是元素属性,第三个参数是用户选项值(自定义数据),第四个参数是选项值(比如下拉列表的值)。

渲染表单元素

  1. <?php
  2.  
  3. echo $element->render();

初始化表单(Initializing forms)

从上面的例子我们可以看到表单项也可以在form对象初始化后进行添加。当然开发者也可以对原有的Form类进行扩展:

  1. <?php
  2.  
  3. use Phalcon\Forms\Form;
  4. use Phalcon\Forms\Element\Text;
  5. use Phalcon\Forms\Element\Select;
  6.  
  7. class ContactForm extends Form
  8. {
  9. public function initialize()
  10. {
  11. $this->add(new Text("name"));
  12.  
  13. $this->add(new Text("telephone"));
  14.  
  15. $this->add(
  16. new Select(
  17. "telephoneType",
  18. TelephoneTypes::find(),
  19. array(
  20. 'using' => array(
  21. 'id',
  22. 'name'
  23. )
  24. )
  25. )
  26. );
  27. }
  28. }

由于 Phalcon\Forms\Form 实现了 Phalcon\Di\Injectable 接口,所以开发者可以根据自己的需要访问应用中的服务。

  1. <?php
  2.  
  3. use Phalcon\Forms\Form;
  4. use Phalcon\Forms\Element\Text;
  5. use Phalcon\Forms\Element\Hidden;
  6.  
  7. class ContactForm extends Form
  8. {
  9. /**
  10. * This method returns the default value for field 'csrf'
  11. */
  12. public function getCsrf()
  13. {
  14. return $this->security->getToken();
  15. }
  16.  
  17. public function initialize()
  18. {
  19. // Set the same form as entity
  20. $this->setEntity($this);
  21.  
  22. // Add a text element to capture the 'email'
  23. $this->add(new Text("email"));
  24.  
  25. // Add a text element to put a hidden CSRF
  26. $this->add(new Hidden("csrf"));
  27. }
  28. }

相关的实体在初始化时添加到表单, 自定义的选项通过构造器传送:

  1. <?php
  2.  
  3. use Phalcon\Forms\Form;
  4. use Phalcon\Forms\Element\Text;
  5. use Phalcon\Forms\Element\Hidden;
  6.  
  7. class UsersForm extends Form
  8. {
  9. /**
  10. * Forms initializer
  11. *
  12. * @param Users $user
  13. * @param array $options
  14. */
  15. public function initialize(Users $user, $options)
  16. {
  17. if ($options['edit']) {
  18. $this->add(new Hidden('id'));
  19. } else {
  20. $this->add(new Text('id'));
  21. }
  22.  
  23. $this->add(new Text('name'));
  24. }
  25. }

在表单实例中必须要这样使用:

  1. <?php
  2.  
  3. $form = new UsersForm(
  4. new Users(),
  5. array(
  6. 'edit' => true
  7. )
  8. );

验证(Validation)

Phalcon表单组件可以和 validation 集成,以提供验证。 开发者要单独为每个html元素提供内置或自定义的验证器。

  1. <?php
  2.  
  3. use Phalcon\Forms\Element\Text;
  4. use Phalcon\Validation\Validator\PresenceOf;
  5. use Phalcon\Validation\Validator\StringLength;
  6.  
  7. $name = new Text("name");
  8.  
  9. $name->addValidator(
  10. new PresenceOf(
  11. array(
  12. 'message' => 'The name is required'
  13. )
  14. )
  15. );
  16.  
  17. $name->addValidator(
  18. new StringLength(
  19. array(
  20. 'min' => 10,
  21. 'messageMinimum' => 'The name is too short'
  22. )
  23. )
  24. );
  25.  
  26. $form->add($name);

然后, 开发者可以根据用户的输入进行验证:

  1. <?php
  2.  
  3. if (!$form->isValid($_POST)) {
  4. foreach ($form->getMessages() as $message) {
  5. echo $message, '<br>';
  6. }
  7. }

验证器执行的顺序和注册的顺序一致。

默认情况下,所有的元素产生的消息是放在一起的, 所以开发者可以使用简单的foreach来遍历消息, 开发者可以按照自己的意愿组织输出:

  1. <?php
  2.  
  3. foreach ($form->getMessages(false) as $attribute => $messages) {
  4. echo 'Messages generated by ', $attribute, ':', "\n";
  5.  
  6. foreach ($messages as $message) {
  7. echo $message, '<br>';
  8. }
  9. }

或获取指定元素的消息:

  1. <?php
  2.  
  3. foreach ($form->getMessagesFor('name') as $message) {
  4. echo $message, '<br>';
  5. }

过滤(Filtering)

表单元素可以在进行验证前先进行过滤, 开发者可以为每个元素设置过滤器:

设置用户选项(Setting User Options)

表单与实体(Forms + Entities)

我们可以把 model/collection/plain 设置到表单对象中, 这样 phalcon 会自动的设置表单元素的值:

  1. <?php
  2.  
  3. $robot = Robots::findFirst();
  4.  
  5. $form = new Form($robot);
  6.  
  7. $form->add(new Text("name"));
  8.  
  9. $form->add(new Text("year"));

在表单渲染时如果表单项未设置默认值, phalcon会使用对象实体值作为默认值:

  1. <?php echo $form->render('name'); ?>

开发者可以使用下面的方式验证表单及利用用户的输入来设置值:

  1. <?php
  2.  
  3. $form->bind($_POST, $robot);
  4.  
  5. // Check if the form is valid
  6. if ($form->isValid()) {
  7.  
  8. // Save the entity
  9. $robot->save();
  10. }

也可以使用一个简单的类做为对象实体进行参数传递:

  1. <?php
  2.  
  3. class Preferences
  4. {
  5. public $timezone = 'Europe/Amsterdam';
  6.  
  7. public $receiveEmails = 'No';
  8. }

使用此类做为对象实体,这样可以使用此类中的值作为表单的默认值:

  1. <?php
  2.  
  3. $form = new Form(new Preferences());
  4.  
  5. $form->add(
  6. new Select(
  7. "timezone",
  8. array(
  9. 'America/New_York' => 'New York',
  10. 'Europe/Amsterdam' => 'Amsterdam',
  11. 'America/Sao_Paulo' => 'Sao Paulo',
  12. 'Asia/Tokyo' => 'Tokyo'
  13. )
  14. )
  15. );
  16.  
  17. $form->add(
  18. new Select(
  19. "receiveEmails",
  20. array(
  21. 'Yes' => 'Yes, please!',
  22. 'No' => 'No, thanks'
  23. )
  24. )
  25. );

实体中也可以使用getters, 这样可以给开发者更多的自由, 当然也会洽使开发稍麻烦一些,不过这是值得的:

  1. <?php
  2.  
  3. class Preferences
  4. {
  5. public $timezone;
  6.  
  7. public $receiveEmails;
  8.  
  9. public function getTimezone()
  10. {
  11. return 'Europe/Amsterdam';
  12. }
  13.  
  14. public function getReceiveEmails()
  15. {
  16. return 'No';
  17. }
  18. }

表单控件(Form Elements)

Phalcon提供了一些内置的html元素类, 所有这些元素类仅位于 Phalcon\Forms\Element 命名空间下:

名称 描述 示例
Text 产生 INPUT[type=text] 项 Example
Password 产生 INPUT[type=password] 项 Example
Select 产生 SELECT tag (combo lists) 项 Example
Check 产生 INPUT[type=check] 项 Example
Textarea 产生 TEXTAREA 项 Example
Hidden 产生 INPUT[type=hidden] 项 Example
File 产生 INPUT[type=file] 项 Example
Date 产生 INPUT[type=date] 项 Example
Numeric 产生 INPUT[type=number] 项 Example
Submit 产生 INPUT[type=submit] 项 Example

事件回调(Event Callbacks)

当扩展表单时, 我们可以在表单类中实现验证前操作及验证后操作:

  1. <?php
  2.  
  3. use Phalcon\Mvc\Form;
  4.  
  5. class ContactForm extends Form
  6. {
  7. public function beforeValidation()
  8. {
  9.  
  10. }
  11. }

渲染表单(Rendering Forms)

开发者对表单的渲染操作有完全的控制,下面的的例子展示了如何使用标准方法渲染html元素:

  1. <?php
  2.  
  3. <form method="post">
  4. <?php
  5. // Traverse the form
  6. foreach ($form as $element) {
  7.  
  8. // Get any generated messages for the current element
  9. $messages = $form->getMessagesFor($element->getName());
  10.  
  11. if (count($messages)) {
  12. // Print each element
  13. echo '<div class="messages">';
  14. foreach ($messages as $message) {
  15. echo $message;
  16. }
  17. echo '</div>';
  18. }
  19.  
  20. echo '<p>';
  21. echo '<label for="', $element->getName(), '">', $element->getLabel(), '</label>';
  22. echo $element;
  23. echo '</p>';
  24.  
  25. }
  26. ?>
  27. <input type="submit" value="Send"/>
  28. </form>

或者可以使用更简单的方式:

  1. <?php
  2.  
  3. echo $form->render();
  4. // or
  5. echo $form->render(NULL, NULL, '<label>:label:</label><p>:element:</p>');

方法 render 第一个参数用来指定渲染哪个表单元素:

  1. <?php
  2.  
  3. echo $form->render('name');

方法 render 第二个参数用来设定表单元素属性:

  1. <?php
  2.  
  3. echo $form->render('name', array('class' => 'form-control'));

方法 render 第三个参数可以设置元素模板:

  1. <?php
  2.  
  3. echo $form->render(NULL, NULL, '<div class="form-group"><label>:label:</label><p>:element:</p></div>');

或是在登录表单中重用表单类:

  1. <?php
  2.  
  3. use Phalcon\Forms\Form;
  4.  
  5. class ContactForm extends Form
  6. {
  7. public function initialize()
  8. {
  9. // ...
  10. }
  11.  
  12. public function renderDecorated($name)
  13. {
  14. $element = $this->get($name);
  15.  
  16. // Get any generated messages for the current element
  17. $messages = $this->getMessagesFor($element->getName());
  18.  
  19. if (count($messages)) {
  20. // Print each element
  21. echo '<div class="messages">';
  22. foreach ($messages as $message) {
  23. echo $this->flash->error($message);
  24. }
  25. echo '</div>';
  26. }
  27.  
  28. echo '<p>';
  29. echo '<label for="', $element->getName(), '">', $element->getLabel(), '</label>';
  30. echo $element;
  31. echo '</p>';
  32. }
  33. }

视图中:

  1. <?php
  2.  
  3. echo $element->renderDecorated('name');
  4.  
  5. echo $element->renderDecorated('telephone');

创建表单控件(Creating Form Elements)

除了可以使用phalcon提供的html元素以外, 开发者还可以使用自定义的html元素:

  1. <?php
  2.  
  3. use Phalcon\Forms\Element;
  4.  
  5. class MyElement extends Element
  6. {
  7. public function render($attributes = null)
  8. {
  9. $html = // ... Produce some HTML
  10. return $html;
  11. }
  12. }

表单元素转换为数组(Creating Form Elements)

  1. <?php
  2.  
  3. $nameElement = new \Phalcon\Forms\Element("name", array('class' => 'big-input'), array('some' => 'value'), NULL, "text");
  4. $versionElement = new \Phalcon\Forms\Element("version", NULL, NULL, array('phalcon' => 'Phalcon', 'phalcon7' => 'Phalcon7'), "select");
  5.  
  6. $form = new \Phalcon\Forms\Form();
  7. $form->add($nameElement);
  8. $form->add($versionElement);
  9. $data = $form->toArray();

$data 值如下:

  1. <?php
  2.  
  3. array(
  4. "name" => array(
  5. "name" => "name",
  6. "type" => "text",
  7. "attributes" => array(
  8. "class" => "big-input",
  9. ),
  10. "options" => array(
  11. "some" => "value",
  12. ),
  13. ),
  14. "version" => array(
  15. "name" => "version",
  16. "type" => "select",
  17. "optionsValues" => array(
  18. "phalcon" => "Phalcon",
  19. "phalcon7" => "Phalcon7",
  20. ),
  21. )
  22. );

表单管理(Forms Manager)

此组件为开发者提供了一个表单管理器, 可以用来注册表单,此组件可以使用服务容器来访问:

  1. <?php
  2.  
  3. use Phalcon\Forms\Manager as FormsManager;
  4.  
  5. $di['forms'] = function () {
  6. return new FormsManager();
  7. };

表单被添加到表单管理器, 然后设置了唯一的名字:

  1. <?php
  2.  
  3. $this->forms->set('login', new LoginForm());

使用唯一名, 我们可以在应用的任何地方访问到表单:

  1. <?php
  2.  
  3. echo $this->forms->get('login')->render();

外部资源(External Resources)

  • Vökuró 是一个使用表单构建器来创建和维护表单的示例 [Github]

原文: http://www.myleftstudio.com/reference/forms.html