`
zhouwei064
  • 浏览: 27270 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

Yii技术框架学习之路(五)

    博客分类:
  • PHP
阅读更多

表单生成器

 

当创建 HTML 表单时,经常我们发现我们在写很多重复而且在不同项目中很难重用的视图代码。 例如,对于每个输入框, 我们需要以一个文本标签和显示可能的验证错误来关联它。 为了改善这些代码的重用性,我们可以使用自版本 1.1.0 可用的表单生成器特征。

1. 基本概念 

Yii 表单生成器使用 CForm 对象来代表描述一个HTML表单所需的内容,包括哪些数据模型关联到此表单, 表单中有哪些输入框,以及如何渲染整个表单。开发者主要需要创建和配置这个 CForm 对象,然后调用它的渲染方法来显示表单。

表单的输入框参数被组织为根据表单元素的分层结构。 在结构的顶层,是 CForm 对象。此对象的成员分为两大类: CForm::buttons 和 CForm::elements。前者包含 按钮元素(例如提交按钮,重设按钮),后者包含输入元素,静态文本和子表单。子表单也是 CForm 对象,只是它存在于 另一个表单的 CForm::elements 中。子表单可以有它自己的数据模型, CForm::buttons 和 CForm::elements 集合。

当用户提交一个表单时,整个表单结构中填写的数据被提交, 也包含子表单中填写的数据。 CForm 提供了便利方法,可以自动赋值输入的数据到对应的数据属性并执行数据验证。

2. 创建一个简单的表单 

下面,我们展示如何使用表单生成器来创建一个登录表单。

首先,我们编写登录 action 代码:

public function actionLogin()
{
    $model = new LoginForm;
    $form = new CForm('application.views.site.loginForm', $model);
    if($form->submitted('login') && $form->validate())
        $this->redirect(array('site/index'));
    else
        $this->render('login', array('form'=>$form));
}

在上面的代码中,我们使用由路径别名 application.views.site.loginForm (将会简要解释) 指定的参数创建了 CForm 对象。 CForm 对象和 LoginForm 模型(在Creating Model中已介绍)关联。

如代码所示,若表单被提交并且所有的输入经过了验证而没有错误,我们将转向用户的浏览器到 site/index 页面。否则, 我们以此表单渲染 login 视图。

路径别名 application.views.site.loginForm 实际指的是 PHP 文件protected/views/site/loginForm.php。此文件应当返回一个 PHP 数组,这个数组代表了 CForm 所需的配置, 如下所示:

return array(
    'title'=>'Please provide your login credential',
 
    'elements'=>array(
        'username'=>array(
            'type'=>'text',
            'maxlength'=>32,
        ),
        'password'=>array(
            'type'=>'password',
            'maxlength'=>32,
        ),
        'rememberMe'=>array(
            'type'=>'checkbox',
        )
    ),
 
    'buttons'=>array(
        'login'=>array(
            'type'=>'submit',
            'label'=>'Login',
        ),
    ),
);

配置是一个由键值对组成的关联数组,被用来初始化 CForm 的对应属性。要配置的最重要的属性,如之前所述,是 CForm::elements 和 CForm::buttons。 它们的每一个是一个指定了表单元素列表的数组。在下一小节我们将给出更多细节关于如何配置表单元素。

最后,我们编写 login 视图,可以简洁地如下所示,

<h1>Login</h1>
 
<div class="form">
<?php echo $form; ?>
</div>

提示: 上面的代码 echo $form; 相当于 echo $form->render();。 这是因为 CForm 执行了__toString 魔术方法,它调用 render() 并返回它的结果为代表此表单对象的字符串。

3. 指定表单元素 

使用表单生成器,我们大部分的工作由编写视图脚本代码转为指定表单元素。在这一小节中,我们讲述如何指定CForm::elements 属性。 我们不准备讲述 CForm::buttons 因为它的配置和 CForm::elements 的配置几乎相同。

CForm::elements 属性接受一个数组作为它的值。每个数组元素指定了一个单独的表单元素,这个表单元素可以是一个输入框,一个静态文本字符串或一个子表单。

指定输入元素

一个输入元素主要由标签,输入框,提示文字和错误显示组成。 它必须和一个模型属性关联。一个输入元素的规格被代表为一个 CFormInputElement 实例。 CForm::elements 数组中的如下代码指定了一个单独的输入元素:

'username'=>array(
    'type'=>'text',
    'maxlength'=>32,
),

它说明模型属性被命名为 username,输入框的类型为 text,它的 maxlength 属性为 32。

任何 CFormInputElement 可写的属性都可以如上配置。例如,我们可以指定 hint 选项来显示提示信息,或者我们可以指定 items 选项若输入框是一个 list box,一个下拉列表,一个多选列表或一个单选按钮列表。 若选项的名字不是一个 CFormInputElement 属性,它将被认为是对应 HTML 输入元素的属性, 例如,因为上面的 maxlength不是一个 CFormInputElement 属性,它被渲染作为 HTML 文本输入框的 maxlength 属性。

type 选项需要特别注意。它指定了输入框的类型。 例如,text 类型意味着将渲染一个普通的文本输入框;password 类型意味着将渲染一个密码输入框。 CFormInputElement 识别如下内置的类型:

  • text
  • hidden
  • password
  • textarea
  • file
  • radio
  • checkbox
  • listbox
  • dropdownlist
  • checkboxlist
  • radiolist

在上面的内置类型中,我们想要对这些 "list" 类型的用法多说一些, 包括 dropdownlist, checkboxlist 和radiolist。这些类型需要设置对应输入元素的 items 属性。可以这样做:

'gender'=>array(
    'type'=>'dropdownlist',
    'items'=>User::model()->getGenderOptions(),
    'prompt'=>'Please select:',
),
 
...
 
class User extends CActiveRecord
{
    public function getGenderOptions()
    {
        return array(
            0 => 'Male',
            1 => 'Female',
        );
    }
}

上面的代码将生成一个下拉列表选择器,提示文字是 “please select:”。选项包括 “Male” 和 “Female”,它们是由User 模型类中的 getGenderOptions 方法返回的。

除了这些内置的类型, type 选项也可以是一个 widget 类名字或 widget 类的路径别名。 widget 类必须扩展自CInputWidget 或 CJuiInputWidget。当渲染输入元素时, 一个指定 widget 类的实例将被创建并渲染。The widget will be configured using the specification as given for the input element.

指定静态文本

很多情况下,一个表单包含一些装饰性的 HTML 代码。 例如,一个水平线被用来分隔表单中不同的部分;一个图像出现在特定的位置来增强表单的视觉外观。 我们可以在 CForm::elements 集合中指定这些 HTML 代码作为静态文本。要这样做,我们只要指定一个静态文本字符串作为一个数组元素,在 CForm::elements 恰当的位置。例如,

return array(
    'elements'=>array(
        ......
        'password'=>array(
            'type'=>'password',
            'maxlength'=>32,
        ),
 
        '<hr />',
 
        'rememberMe'=>array(
            'type'=>'checkbox',
        )
    ),
    ......
);

在上面,我们在 password 输入框和 rememberMe 之间插入一个水平线。

静态文本最好用于文本内容和它们的位置不规则时。 若表单中的每个输入元素需要被相似的装饰,我们应当定制表单渲染方法,此章节将简短介绍。

指定子表单

子表单被用来分离一个长的表单为几个逻辑部分。 例如,我们可以分离用户注册表单为两部分:登录信息和档案信息。 每个子表单和一个数据模型有无关联均可。例如在用户注册表单,若我们存储用户登录信息和档案信息到两个分离的数据表中(表示为两个数据模型), 然后每个子表单需要和一个对应的数据模型关联。若我们存储所有信息到一个数据表中,任意一个子表单都没有数据模型,因为它们和根表单分享相同的模型。

一个子表单也表示为一个CForm 对象。要指定一个子表单,我们应当配置 CForm::elements 属性为一个类型是form 的元素:

return array(
    'elements'=>array(
        ......
        'user'=>array(
            'type'=>'form',
            'title'=>'Login Credential',
            'elements'=>array(
                'username'=>array(
                    'type'=>'text',
                ),
                'password'=>array(
                    'type'=>'password',
                ),
                'email'=>array(
                    'type'=>'text',
                ),
            ),
        ),
 
        'profile'=>array(
            'type'=>'form',
            ......
        ),
        ......
    ),
    ......
);

类似于配置一个根表单,我们主要需要为一个子表单指定 CForm::elements 属性。若一个子表单需要关联一个数据模型,我们也可以配置它的 CForm::model 属性。

有时,我们想要使用一个类代表表单,而不使用默认的 CForm 类。例如, 此小节将简短展示,我们可以扩展CForm 以定制表单渲染逻辑。 通过指定输入元素的类型为 form,一个子表单将自动被表示为一个对象,它的类和它的父表单相同。若我们指定输入元素的类型类似于 XyzForm (一个以 Form 结尾的字符串), 然后子表单将被表示为一个 XyzForm 对象。

4. 访问表单元素 

访问表单元素和访问数组元素一样简单。CForm::elements 属性返回一个 CFormElementCollection 对象, 它扩展自 CMap 并允许以类似于一个普通数组的方式来访问它的元素。例如,要访问登录表单中的元素 username,我们可以使用下面的代码:

$username = $form->elements['username'];

要访问用户注册表单中的 email 元素,使用

$email = $form->elements['user']->elements['email'];

因为 CForm 为它的 CForm::elements 属性执行数组访问,上面的代码可以简化为:

$username = $form['username'];
$email = $form['user']['email'];

5. 创建一个嵌套表单 

我们已经描述了子表单。我们称一个有子表单的表单为一个嵌套表单。在这一章节, 我们使用用户注册表单作为例子来展示如何创建一个关联多个数据模型的嵌套表单。我们假设用户的认证信息存储为一个 User 模型,而用户的档案信息被存储为一个 Profile 模型。

我们首先创建 register action 如下:

public function actionRegister()
{
    $form = new CForm('application.views.user.registerForm');
    $form['user']->model = new User;
    $form['profile']->model = new Profile;
    if($form->submitted('register') && $form->validate())
    {
        $user = $form['user']->model;
        $profile = $form['profile']->model;
        if($user->save(false))
        {
            $profile->userID = $user->id;
            $profile->save(false);
            $this->redirect(array('site/index'));
        }
    }
 
    $this->render('register', array('form'=>$form));
}

在上面,我们使用由 application.views.user.registerForm 指定的配置创建了表单。 在表单被提交且成功验证之后,我们尝试保存 user 和 profile 模型。 我们通过访问相应子表单对象的 model 属性来检索 user 和 profile 模型。 因为输入验证已经完成,我们调用 $user->save(false) 来跳过验证。为 profile 模型也这样做。

接下来,我们编写表单配置文件 protected/views/user/registerForm.php

return array(
    'elements'=>array(
        'user'=>array(
            'type'=>'form',
            'title'=>'Login information',
            'elements'=>array(
                'username'=>array(
                    'type'=>'text',
                ),
                'password'=>array(
                    'type'=>'password',
                ),
                'email'=>array(
                    'type'=>'text',
                )
            ),
        ),
 
        'profile'=>array(
            'type'=>'form',
            'title'=>'Profile information',
            'elements'=>array(
                'firstName'=>array(
                    'type'=>'text',
                ),
                'lastName'=>array(
                    'type'=>'text',
                ),
            ),
        ),
    ),
 
    'buttons'=>array(
        'register'=>array(
            'type'=>'submit',
            'label'=>'Register',
        ),
    ),
);

在上面,当指定每个子表单时,我们也指定它的 CForm::title 属性。 默认的表单渲染逻辑将封装每个子表单到一个 field-set 中,使用此属性作为它的标题。

最后,我们编写 register 视图脚本:

<h1>Register</h1>
 
<div class="form">
<?php echo $form; ?>
</div>

6. 定制表单显示 

使用表单生成器最主要的好处是逻辑 (表单配置被存储在一个单独的文件中) 和表现 (CForm::render方法) 的分离。 这样,我们可以实现定制表单显示,通过重写 CForm::render 或提供一个局部视图来渲染表单。两种方法都可以保持表单配置的完整性,并且可以容易地重用。

当重写 CForm::render 时, 你主要需要遍历 CForm::elements 和 CForm::buttons 并调用每个表单元素的CFormElement::render 方法。例如,

class MyForm extends CForm
{
    public function render()
    {
        $output = $this->renderBegin();
 
        foreach($this->getElements() as $element)
            $output .= $element->render();
 
        $output .= $this->renderEnd();
 
        return $output;
    }
}

可能我们也需要写一个视图脚本 _form 以渲染一个视图:

<?php
echo $form->renderBegin();
 
foreach($form->getElements() as $element)
    echo $element->render();
 
echo $form->renderEnd();

要使用此视图脚本,我们需要调用:

<div class="form">
$this->renderPartial('_form', array('form'=>$form));
</div>

若一个通用的表单渲染不适用于一个特殊的表单(例如,表单为特定的元素需要不规则的装饰),在视图脚本中我们可以这样做:

some complex UI elements here
 
<?php echo $form['username']; ?>
 
some complex UI elements here
 
<?php echo $form['password']; ?>
 
some complex UI elements here

在最后的方法中,表单生成器看起来并没有带来好处,因为我们仍然需要写很多表单代码。然而,它仍然是有好处的,表单被使用一个分离的配置文件指定,这样可以帮助开发者更专注于逻辑部分。

分享到:
评论

相关推荐

    yii框架中文手册教程

    1. 性能优越:Yii框架采用了各种优化技术,保证了Web应用的高性能,尤其在处理大量数据和高流量的Web应用时表现优异。 2. 组件化设计:Yii框架采用基于组件的设计模式,开发者可以通过复用组件快速组装出复杂的Web...

    《Yii框架深度剖析》配套代码

    《Yii框架深度剖析》配套代码 本书不是简单地介绍如何使用 Yii 框架,而是站在框架设计的高度,从源代码级别深 度剖析。... 充分了解了这部分知识后,读者对 Yii 框架也有了初步认识,然后正式进入 Yii 框架的学习。

    php最新框架YII框架

    五、学习和开发资源: 为了更好地理解和使用Yii框架,开发者可以参考官方文档、社区论坛、教程和示例代码。官方文档详尽介绍了框架的各个方面,社区则提供了丰富的经验和问题解答。 总结,Yii框架作为PHP开发的利器...

    yii框架中文文档、yii中文手册教程

    Yii框架以性能优化为设计核心,提供了一系列现代化的Web开发工具和技术,使得开发者可以快速、高效地编写高质量的代码。 在“yii1.1中文文档”中,包含了Yii 1.1版本的详尽教程和参考指南。这个版本是Yii框架的一个...

    Yii框架详解

    总结,Yii框架凭借其高效、易用和安全的特性,成为PHP开发者构建大型Web应用的首选之一。通过深入学习Yii,开发者可以提高开发效率,同时保证应用的稳定性和安全性。无论你是初学者还是经验丰富的开发者,Yii都有...

    yii框架中文版手册pdf和chm格式

    - **PDF手册**:提供详细的API文档和技术指南,是学习Yii的重要资料。 - **CHM手册**:另一种格式的手册,适合离线查阅,同样包含了完整的框架指南和参考信息。 4. **开发流程**: - **配置**:通过配置文件设置...

    2014年辛星PHP教程秋季版之yii框架教程

    在深入学习2014年辛星PHP教程秋季版之Yii框架教程之前,我们需要明确几个核心概念。 首先,Yii是一个高级的PHP框架,广泛应用于Web开发,以敏捷和性能著称。它的核心思想包括快速开发、安全性以及专业性,旨在为...

    YII框架实例视频后盾网马振宇

    根据提供的文件信息,我们可以推断出本视频教程主要围绕YII框架进行讲解,特别是YII2版本的应用。...通过学习本教程,不仅可以掌握YII2框架的核心概念和技术要点,还能学会如何利用这些知识构建实用的Web应用程序。

    2016最全Yii框架

    教程名称: 2016最全Yii框架 YII是目前比较火的框架,框架里面使用了最新的技术和设计,可以说学习了YII就学习了最新的php技术,本课程主要学习XSS、CSRF、SQL注入、文件上传漏洞等攻击方式,以及YII框架对它们的...

    配合《带有sphinx搜索功能的yii2框架实例》的资源

    在《带有sphinx搜索功能的yii2框架实例》这本书中,作者可能详细介绍了如何在Yii2框架中配置和使用Sphinx或CoreSeek。这可能包括以下步骤: 1. **安装与配置**:首先,你需要在服务器上安装Sphinx或CoreSeek,然后...

    基于Yii2.0框架深度重构的B2B2C多用户商城系统

    在技术栈方面,虽然标签中提到了"C#",但考虑到ShopWind是基于PHP的Yii2.0框架构建,我们推测这可能是项目中涉及的其他技术或服务的一部分。例如,可能使用了C#开发了与PHP系统交互的API接口,或者是构建了前后端...

    YII框架安装包和详细说明

    这个压缩包包含了用于学习和使用Yii框架的关键资源,包括框架的核心代码、安装指南、使用文档以及一些额外的参考资料。 首先,`yii-1.1.6.r2877.tar.gz` 是Yii框架的一个特定版本,1.1.6,版本号r2877,这通常是一...

    YiiFrame 是一个基于Yii2+Bootstrap的快速后台开发框架

    通过阅读和修改这些源码,开发者可以学习到如何自定义和扩展Yii2框架,以及如何结合Bootstrap来定制前端界面。 总的来说,YiiFrame提供了一个完整的开发环境,涵盖了从后端逻辑到前端展示的各个环节。无论是初学者...

    YII 1.1 Application Development Cookbook

    《YII 1.1 应用开发食谱》是一本深入探讨...总之,《YII 1.1 应用开发食谱》不仅是一本技术指南,更是开发者提升技能、加速项目开发的宝贵资源。无论是新手还是有经验的开发者,都能从中获得有价值的见解和实用的技巧。

    yii框架2.0

    - **Yii** 团队密切关注业界最新的Web开发技术,并在框架中积极采用这些技术。例如,在**Yii 2.0** 中可以看到对PHP最新特性的支持,如命名空间等。 - 这种跟随技术潮流的做法确保了**Yii** 框架始终保持活力和...

    uniapp源码外卖联盟小程序-后台PHP源码Yii框架开发的DuAdmin后台源码-.zip

    总的来说,这个项目涵盖了前端开发、后端开发、框架应用、小程序开发以及私域流量运营等多个层面,对于想要深入学习这些领域的开发者来说,这是一个非常有价值的学习和实践资源。同时,由于项目完全开源,对于有志于...

    yii框架中文手册及中文教程手册

    在中文教程中,你将学习到如何安装Yii框架,如何配置环境,如何创建项目结构,以及如何使用Yii的组件和服务。教程会详细解释每个关键概念,如路由、控制器、视图和模型的创建,以及如何利用Yii的模板引擎来美化输出...

    yii项目源代码

    本项目源代码是基于Yii框架构建的一个实际应用,对于初学者而言,这是一个很好的学习资源,能够帮助他们深入理解Yii的工作原理和最佳实践。 首先,让我们详细了解一下Yii框架的核心特性。Yii提供了一种模型-视图-...

Global site tag (gtag.js) - Google Analytics