Skip to content

Tutorial.Form Generation and Validation II.zh_cn

linzongshu edited this page Jul 4, 2013 · 2 revisions

English

  1. 添加其他类型的表单

3.1 创建注册页

接下来两节,我将以注册页面为例介绍下如何添加其他类型的表单、添加自定义表单以及自定义表单验证。

在Form目录下创建RegisterForm.php文件,并添加如下代码:

路径:usr/module/member/src/Form/RegisterForm.php

Code 3.3.1

<?php
namespace Module\Member\Form;

use Pi\Form\Form as BaseForm;

class RegisterForm extends BaseForm
{
    public function init()
    {
        $this->add(array(
            'name'          => 'username',
            'options'       => array(
                'label'     => __('Username'),
            ),
            'attributes'    => array(
                'type'      => 'text',
            ),
        ));

        $this->add(array(
            'name'          => 'password',
            'options'       => array(
                'label'     => __('Password'),
            ),
            'attributes'    => array(
                'type'      => 'password',
            ),
        ));

        $this->add(array(
            'name'          => 'repeat-password',
            'options'       => array(
                'label'     => __('Repeat Password'),
            ),
            'attributes'    => array(
                'type'      => 'password',
            ),
        ));

        $this->add(array(
            'name'          => 'gender',
            'options'       => array(
                'label'     => __('Gender'),
            ),
            'attributes'    => array(
                'value'     => 'm',
                'options'   => array(
                    'm'         => __('Male'),
                    'f'         => __('Female'),
                ),
            ),
            'type'          => 'radio',
        ));

        $this->add(array(
            'name'          => 'country',
            'options'       => array(
                'label'     => __('Country'),
            ),
            'attributes'    => array(
                'type'      => 'select',
                'value'     => 'chn',
                'options'   => array(
                    'chn'       => __('China'),
                    'usa'       => __('United States'),
                ),
            ),
        ));

        $this->add(array(
            'name'          => 'feedback',
            'options'       => array(
                'label'     => __('Do you want to contact us?'),
            ),
            'attributes'    => array(
                'value'     => 0,
            ),
            'type'          => 'checkbox',
        ));

        $this->add(array(
            'name'          => 'introduction',
            'options'       => array(
                'label'     => __('Introduction'),
            ),
            'attributes'    => array(
                'type'      => 'textarea',
                'cols'      => 50,
                'rows'      => 5,
            ),
        ));

        $this->add(array(
            'name'          => 'submit',
            'attributes'    => array(
                'value'     => __('Create'),
            ),
            'type'          => 'submit',
        ));
    }
}

在这段代码里,我们创建几种类型的表单,包括text, password, radio, select, checkbox, textarea和submit。像radio, select和checkbox/multiCheckbox这几类可能会生成多个表单的的表单,需要在attributes字段里增加options字段来标识不同的表单,这些表单都在同一个组里,而value值就是默认被选中的表单,其值也就是options里的键值。需要注意的是,radio和checkbox的type字段不能写在attributes数组里,否则会报错。另外attributes里还可以添加其他参数,如'class' => 'btn'将会生成class="btn",这样开发者也可以自定义表单标签里的内容。

在src/Controller/Front目录下创建RegisterController.php并添加如下代码:

路径:usr/module/member/src/Controller/Front/RegisterController.php

Code 3.3.2

<?php
namespace Module\Member\Controller\Front;
use Pi\Mvc\Controller\ActionController;
use Module\Member\Form\RegisterForm;

class RegisterController extends ActionController
{
    protected function renderForm()
    {
        $form = new RegisterForm('register');
        $form->setAttribute('action', $this->url('', array('action' => 'index')));

        return $form;
    }

    public function indexAction()
    {
        $form = $this->renderForm();

        $this->view()->assign('form', $form);
        $this->view()->assign('title', __('Register member'));
    }
}

在template/front目录下创建register-index.phtml并添加如下代码:

路径:usr/module/member/template/register-index.phtml

Code 3.3.3

<h2><?php echo $title; ?></h2>

<?php if (isset($error)) {
    echo $error;
} ?>

<?php echo $this->form()->openTag($form) ?>
<div id="member-register-username">
<?php $element = $form->get('username'); ?>
    <div><?php echo $this->formLabel($element) ?></div>
    <div><?php
        echo $this->formElement($element);
        echo $this->formElementErrors($element); ?>
    </div>
</div>

<div id="member-register-password">
<?php $element = $form->get('password'); ?>
    <div><?php echo $this->formLabel($element) ?></div>
    <div><?php
        echo $this->formElement($element);
        echo $this->formElementErrors($element); ?>
    </div>
</div>

<div id="member-register-repeat-password">
<?php $element = $form->get('repeat-password'); ?>
    <div><?php echo $this->formLabel($element) ?></div>
    <div><?php
        echo $this->formElement($element);
        echo $this->formElementErrors($element); ?>
    </div>
</div>

<div id="member-register-gender">
<?php $element = $form->get('gender'); ?>
    <div><?php echo $this->formLabel($element) ?></div>
    <div><?php
        echo $this->formElement($element);
        echo $this->formElementErrors($element); ?>
    </div>
</div>

<div id="member-register-country">
<?php $element = $form->get('country'); ?>
    <div><?php echo $this->formLabel($element) ?></div>
    <div><?php
        echo $this->formElement($element);
        echo $this->formElementErrors($element); ?>
    </div>
</div>

<div id="member-register-feedback">
<?php $element = $form->get('feedback'); ?>
    <div><?php
        echo $this->formElement($element);
        echo $this->formElementErrors($element); ?>
    </div>
</div>

<div id="member-register-introduction">
<?php $element = $form->get('introduction'); ?>
    <div><?php echo $this->formLabel($element) ?></div>
    <div><?php
        echo $this->formElement($element);
        echo $this->formElementErrors($element); ?>
    </div>
</div>

<div id="login-login-submit">
<?php $element = $form->get('submit'); ?>
    <div><?php echo $this->formElement($element) ?></div>
</div>
<?php echo $this->form()->closeTag() ?>

在浏览器访问localhost/course/www/member/register将会看下如下页面:

fig3-5

图3-5 member模块注册页

3.2 扩展表单

上述例子中,我们只是将所有的配置参数通过add()方法传递给Form类,对于country我们只是写了两条记录,但实际上这一项会有一两百条记录,如果都只是通过这种方式添加,会使代码难以阅读,并且工作量也很大,一般这种数据可以保存在数据库或文件里,因此我们可以创建一个类继承自Select类,动态生成表单。在此以select表单为例介绍下如何动态创建表单。

首先需要修改RegisterForm类里country表单的类型:

路径:usr/module/member/src/Form/RegisterForm.php

Code 3.3.4

...
    $this->add(array(
        'name'          => 'country',
        'options'       => array(
            'label'     => __('Country'),
        ),
        'type'      => 'Module\Member\Form\Element\CountrySelect',
    ));
....

在代码里,我们把type的类型修改为一个命名空间的形式,CountrySelect就是我们要创建的类。需要注意的是,type字段此时不能放在attributes数组里,否则会报错。根据这个命名规则,我们需要在Form目录下创建Element目录,并在Element里创建CountrySelect.php文件。

member
|- src
   |- Form
      |- Element
         |- CountrySelect.php

路径:usr/module/member/src/Form/Element/CountrySelect.php

Code 3.3.5

<?php
namespace Module\Member\Form\Element;

use Zend\Form\Element\Select;

class CountrySelect extends Select
{
    protected $countries = array(
        'chn'    => 'China',
        'usa'    => 'United States',
        'jpn'    => 'Japan',
        'uk'     => 'United Kindom',
    );

    public function getValueOptions()
    {
        if (empty($this->valueOptions)) {
            foreach ($this->countries as $key => $country) {
                $options[$key] = __($country);
            }
            $this->valueOptions = $options;
        }

        return $this->valueOptions;
    }
}

在这段代码里,我们首先定义了命名空间,同时引用了CountrySelect类要继承的类-- Zend\Form\Element\Select,这个就是之前在RegisterForm里指定的select类型对应的类。

在类里,由于暂时还没介绍数据库操作,我们这里手动添加了一些国家的信息,同时创建getValueOptions()方法来覆盖基类的这个方法,在getValueOptions()里,我们把coutries里的值都添加翻译,然后赋给valueOptions变量,这样select里的值就被更改了。

fig3-6

图3-6 表单扩展

开发者可以运用同样的方法来扩展其他表单,实现自定义功能。

[Form Generation and Validation III](Tutorial.Form Generation and Validation III)

Clone this wiki locally