表单(Forms)

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

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

  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(
  7. new Text(
  8. "name"
  9. )
  10. );
  11. $form->add(
  12. new Text(
  13. "telephone"
  14. )
  15. );
  16. $form->add(
  17. new Select(
  18. "telephoneType",
  19. [
  20. "H" => "Home",
  21. "C" => "Cell",
  22. ]
  23. )
  24. );

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

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

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

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

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

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

初始化表单(Initializing forms)

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

  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(
  10. new Text(
  11. "name"
  12. )
  13. );
  14. $this->add(
  15. new Text(
  16. "telephone"
  17. )
  18. );
  19. $this->add(
  20. new Select(
  21. "telephoneType",
  22. TelephoneTypes::find(),
  23. [
  24. "using" => [
  25. "id",
  26. "name",
  27. ]
  28. ]
  29. )
  30. );
  31. }
  32. }

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

  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(
  20. new Text(
  21. "email"
  22. )
  23. );
  24. // Add a text element to put a hidden CSRF
  25. $this->add(
  26. new Hidden(
  27. "csrf"
  28. )
  29. );
  30. }
  31. }

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

  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(Users $user, array $options)
  14. {
  15. if ($options["edit"]) {
  16. $this->add(
  17. new Hidden(
  18. "id"
  19. )
  20. );
  21. } else {
  22. $this->add(
  23. new Text(
  24. "id"
  25. )
  26. );
  27. }
  28. $this->add(
  29. new Text(
  30. "name"
  31. )
  32. );
  33. }
  34. }

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

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

验证(Validation)

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

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

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

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

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

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

  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. }

或获取指定元素的消息:

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

过滤(Filtering)

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

  1. <?php
  2. use Phalcon\Forms\Element\Text;
  3. $name = new Text(
  4. "name"
  5. );
  6. // Set multiple filters
  7. $name->setFilters(
  8. [
  9. "string",
  10. "trim",
  11. ]
  12. );
  13. $form->add($name);
  14. $email = new Text(
  15. "email"
  16. );
  17. // Set one filter
  18. $email->setFilters(
  19. "email"
  20. );
  21. $form->add($email);

Learn more about filtering in Phalcon by reading the Filter documentation.

表单与实体(Forms + Entities)

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

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

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

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

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

  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. }

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

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

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

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

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

  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\Forms\Element\Text产生 INPUT[type=text] 项
Phalcon\Forms\Element\Password产生 INPUT[type=password] 项
Phalcon\Forms\Element\Select产生 SELECT tag (combo lists) 项
Phalcon\Forms\Element\Check产生 INPUT[type=check] 项
Phalcon\Forms\Element\TextArea产生 TEXTAREA 项
Phalcon\Forms\Element\Hidden产生 INPUT[type=hidden] 项
Phalcon\Forms\Element\File产生 INPUT[type=file] 项
Phalcon\Forms\Element\Date产生 INPUT[type=date] 项
Phalcon\Forms\Element\Numeric产生 INPUT[type=number] 项
Phalcon\Forms\Element\Submit产生 INPUT[type=submit] 项

事件回调(Event Callbacks)

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

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

渲染表单(Rendering Forms)

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

  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(
  8. $element->getName()
  9. );
  10. if (count($messages)) {
  11. // Print each element
  12. echo '<div class="messages">';
  13. foreach ($messages as $message) {
  14. echo $message;
  15. }
  16. echo "</div>";
  17. }
  18. echo "<p>";
  19. echo '<label for="', $element->getName(), '">', $element->getLabel(), "</label>";
  20. echo $element;
  21. echo "</p>";
  22. }
  23. ?>
  24. <input type="submit" value="Send" />
  25. </form>

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

  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(
  14. $element->getName()
  15. );
  16. if (count($messages)) {
  17. // Print each element
  18. echo '<div class="messages">';
  19. foreach ($messages as $message) {
  20. echo $this->flash->error($message);
  21. }
  22. echo "</div>";
  23. }
  24. echo "<p>";
  25. echo '<label for="', $element->getName(), '">', $element->getLabel(), "</label>";
  26. echo $element;
  27. echo "</p>";
  28. }
  29. }

视图中:

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

创建表单控件(Creating Form Elements)

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

  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)

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

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

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

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

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

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

外部资源(External Resources)

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