表单Forms

Phalcon中提供了 Phalcon\Forms组件以方便开发者创建和维护应用中的表单。 下面的例子中展示了基本的使用方法:

Phalcon\Forms is a component that aid the developer in the creation and maintenance of forms in web applications.

The following example shows its basic usage:

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

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

Forms can be rendered based on the form definition:

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

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

Each element in the form can be rendered as required by the developer. Internally, Phalcon\Tag is used to produce the right HTML for each element, you can pass additional html attributes as second parameter for render:

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

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

HTML Attributes also can be set in the element’s definition:

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

初始化表单Initializing forms

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

As seen before, forms can be initialized outside the form class by adding elements to it. You can re-use code or organize your form classes implementing the form in a separated file:

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

由于 :doc:`Phalcon\Forms\Form <../api/Phalcon_Forms_Form>`实现了 :doc:`Phalcon\DI\Injectable <../api/Phalcon_DI_Injectable>`接口, 所以开发者可以根据自己的需要访问应用中的服务。

Phalcon\Forms\Form extends Phalcon\DI\Injectable so you have access to the application services if needed:

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

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

The associated entity added to the form in the initialization and custom user options are passed to the form constructor:

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

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

In the form’s instantiation you must use:

  1. <?php
  2. $form = new UsersForm(new Users(), array('edit' => true));

验证Validation

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

Phalcon forms are integrated with the validation component to offer instant validation. Built-in or custom validators could be set to each element:

  1. <?php
  2. use Phalcon\Forms\Element\Text;
  3. use Phalcon\Validation\Validator\PresenceOf;
  4. use Phalcon\Validation\Validator\StringLength;
  5. $name = new Text("name");
  6. $name->addValidator(new PresenceOf(array(
  7. 'message' => 'The name is required'
  8. )));
  9. $name->addValidator(new StringLength(array(
  10. 'min' => 10,
  11. 'messageMinimum' => 'The name is too short'
  12. )));
  13. $form->add($name);

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

Then you can validate the form according to the input entered by the user:

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

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

Validators are executed in the same order as they were registered.

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

By default messages generated by all the elements in the form are joined so they can be traversed using a single foreach, you can change this behavior to get the messages separated by the field:

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

或获取指定元素的消息:

Or get specific messages for an element:

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

过滤Filtering

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

A form is also able to filter data before it is validated. You can set filters in each element:

设置用户选项Setting User Options

表单与实体Forms + Entities

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

An entity such as a model/collection/plain instance or just a plain PHP class can be linked to the form in order to set default values in the form’s elements or assign the values from the form to the entity easily:

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

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

Once the form is rendered if there is no default values assigned to the elements it will use the ones provided by the entity:

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

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

You can validate the form and assign the values from the user input in the following way:

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

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

Setting up a plain class as entity also is possible:

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

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

Using this class as entity, allows the form to take the default values from it:

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

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

Entities can implement getters, which have a higher precedence than public properties. These methods give you more freedom to produce values:

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

表单控件Form Elements

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

Phalcon provides a set of built-in elements to use in your forms, all these elements are located in the Phalcon\Forms\Element namespace:

NameDescriptionExample
TextGenerate INPUT[type=text] elementsExample
PasswordGenerate INPUT[type=password] elementsExample
SelectGenerate SELECT tag (combo lists) elements based on choicesExample
CheckGenerate INPUT[type=check] elementsExample
TextareaGenerate TEXTAREA elementsExample
HiddenGenerate INPUT[type=hidden] elementsExample
FileGenerate INPUT[type=file] elementsExample
DateGenerate INPUT[type=date] elementsExample
NumericGenerate INPUT[type=number] elementsExample
SubmitGenerate INPUT[type=submit] elementsExample

事件回调Event Callbacks

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

Whenever forms are implemented as classes, the callbacks: beforeValidation and afterValidation can be implemented in the form’s class to perform pre-validations and post-validations:

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

渲染表单Rendering Forms

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

You can render the form with total flexibility, the following example shows how to render each element using an standard procedure:

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

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

Or reuse the logic in your form class:

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

视图中:

In the view:

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

创建表单控件Creating Form Elements

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

In addition to the form elements provided by Phalcon you can create your own custom elements:

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

表单管理Forms Manager

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

This component provides a forms manager that can be used by the developer to register forms and access them via the service locator:

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

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

Forms are added to the forms manager and referenced by a unique name:

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

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

Using the unique name, forms can be accessed in any part of the application:

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

外部资源External Resources

[Vökuró <http://vokuro.phalconphp.com>\`\_是一个使用表单构建器来创建和维护表单的示例 [`Github](https://github.com/phalcon/vokuro)\]

  • Vökuró, is a sample application that uses the forms builder to create and manage forms, [Github]