让我们使用 fuelphp 的 fieldset 来快速、优雅且广泛地批量生成输入表单。

大家好,
我是开发团队里的“野孩子”Mandai。
我们公司FuelPHP,但最近遇到了人手不足的问题,无法逐个创建表单。于是,我们采用了fieldset进行批量生产,大大减少了工作量,最近我们对此非常满意。
这次,我想和大家分享一下fieldset的精髓。
请注意,本文内容已在FuelPHP 1.7.2版本中验证有效。

 

什么是字段集?

我认为 fieldset 是 FuelPHP 快速开发能力的缩影,但令人惊讶的是,日语中关于它的深入文章似乎很少。
不过,有很多文章只是简单地说“我试用了一下”。fieldset
是一种机制,它基于模型中定义的信息,通过一次方法调用即可创建表单。
如果你使用的是基于标准 Twitter Bootstrap 的 Web 应用程序,
那么在忽略一些细节的情况下,你无需编写任何 HTML 代码即可输出表单部分。

一旦你精心编写好模型,就可以依靠字段集一次性创建所有内容。因此,如果你
有很多输入屏幕需要处理,而且你的日程安排让你不得不赶到末班车回家,请考虑使用此选项,希望它能帮助你抽出一些时间陪伴家人。

 

那么,让我们来编写一个模型吧。

使用字段集时,生成表单所需的所有信息都放在 `$_pr​​operties` 中。
这包括输入类型和验证规则,从而可以集中管理表单信息。
例如,我们创建一个基于图书登记页面的 `Model_Book` 类。

书桌的样子是这样的:

CREATE TABLE `books` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `title` varchar(512) NOT NULL, `author` varchar(256) NOT NULL, `price` int(10) unsigned NOT NULL, `isbn` varchar(13) DEFAULT '', `released_at` date DEFAULT '0000-00-00', `type` tinyint(2) DEFAULT NULL, `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 
请按如下方式定义此书籍表的模型:

<?php // fuel/app/classes/model/book.php class Model_Book extends \Model\Orm { protected static $_connection = 'default'; protected static $_table_name = 'books'; protected static $_properties = [ 'id', 'title' => [ 'data_type' => 'varchar', 'label' => 'title', 'validation' => [ 'required', 'max_length' => [512], ], 'form' => [ 'type' => 'text', 'class' => 'form-control', ], ], 'author' => [ 'data_type' => 'varchar', 'label' => 'author', 'validation' => [ 'required', 'max_length' => [512], ], 'form' => [ 'type' => 'text', 'class' => 'form-control', ], ], 'price' => [ 'data_type' => 'int', 'label' => 'price', 'validation' => [ 'required', 'numeric_min' => [0], ], 'form' => [ 'type' => 'number', 'class' => 'form-control', 'min' => 0, ], ], 'isbn' => [ 'data_type' => 'varchar', 'label' => 'ISBN', 'validation' => [ 'match_pattern' => ['/^[0-9]{10}([0-9]{3})?$/'], ], 'form' => [ 'type' => 'text', 'class' => 'form-control', ], ], 'released_at' => [ 'data_type' => 'date', 'label' => 'issue date', 'validation' => [ 'valid_date' => [], ], 'form' => [ 'type' => 'text', 'class' => 'form-control datepicker', ], ], 'type' => [ 'date_type' => 'tinyint', 'label' => 'format', 'validation' => [ 'numeric_min' => [0], ], 'form' => [ 'type' => 'select', 'class' => 'form-control', 'options' => [ 0 => '未知', 1 => 'A4 尺寸', 2 => 'A5 尺寸', 3 => 'A6 尺寸', 4 => 'B4 尺寸', 5 => 'B5 尺寸', 6 => 'B6 尺寸', 7 => '小 B6 尺寸', 8 => '菊本尺寸', 9 => '国际尺寸', 10 => 'AB 尺寸', 11 => '重箱版', 12 => '菊尺寸', 13 => '四目尺寸', 14 => 'B40 尺寸', 15 => '袖珍书version', 16 => 'Sango size', 17 => 'Ochiori size', 18 => 'HL size', ], ], ], 'created_at' => [ 'form' => ['type' => false], ], 'updated_at' => [ 'form' => ['type' => false], ], ]; protected static $_observers = [ 'Orm\Observer_CreatedAt' => [ 'events' => ['before_insert'], 'mysql_timestamp' => true, ], 'Orm\Observer_UpdatedAt' => [ 'events' => ['before_update'], 'mysql_timestamp' => true, ], ]; }

 
这基本涵盖了所有必要信息。
这些信息组织得非常简洁,并以结构化数组的形式编写,这降低了出错的几率,也
方便后续修改。
标准的验证规则FuelPHP 文档的“验证 - 类”部分,让我们好好利用它们。

表单创建相关信息位于每个字段的“form”键下。
“type”对应于input标签的type属性,其用法与常用的text、select、hidden、checkbox和radio标签(包括textarea标签)相同。
对于type="select"、type="checkbox"和type="radio",您可以通过在“options”下将option元素写成数组来定义固定值。

此外,如果该值不是固定的,您可以按如下方式在控制器的选项中设置数据。

$form = \Fieldset::forge('default', [ 'form_attributes' => ['class' => 'form-horizo​​ntal'] ])->add_model('Model_Book'); $newspaper_types = [ 19 => 'Broadsheet', 20 => 'Nordic', 21 => 'Rhenish', 22 => 'Swiss (NZZ)', 23 => 'Berliner', 24 => 'Tabloid Extra', 25 => 'Half Swiss', 26 => 'Half Berliner', 27 => 'Half Rhenish', 28 => 'Half Broadsheet', 29 => 'Tabloid', ]; // 添加字段 $form->field('type')->set_options($newspaper_types); // 要替换字段 $form->field('type')->set_options($newspaper_types, null, true);

 
将 `set_options` 方法的第三个参数设置为 `true` 会覆盖数组而不合并它们。
这样可以轻松地先只输入模型中未选择的值,然后再根据需要添加其他可能的值。

您可以使用 `$form->field('type')` 直接操作表单元素,因此如果您记住了这个表单,
即使您只想在特定情况下稍微更改其外观,也可以在控制器中对其进行控制。
连接到 `$form->field('type')` 并执行各种操作的方法位于 `fuel/core/classes/fieldset/field.php` 文件中。
如果您也查看该文件中的方法,应该能够找到适合您需求的方法。

 

创建一个包含单个方法的表单

模型定义完成后,剩下的就是在控制器中进行微调并生成 HTML。
我所说的微调是指调整表单,否则表单会缺少提交按钮。
你可能会想,“既然是表单,提交按钮肯定必不可少,对吧?”,但
与 CakePHP 不同,FuelPHP 的理念是避免不必要的干预。

$form->add('submit', ' ', ['type'=>'submit', 'class'=>'btn btn-primary submit', 'value' => 'registration']);

 
不过,既然内容就这些,你基本上可以直接复制粘贴。

最后,我们将表单的 HTML 代码传递给视图。
如果控制器继承自 Controller_Template,我们只需使用以下步骤生成视图,然后将构建表单的方法的输出传递给它即可。

$this->template->content = View::forge('manager/master/form.php', $this->contents); $this->template->content->set_safe('form', $form->build());

 
FuelPHP 会自动转义传递给视图的字符串。
但是,如果您想在不转义的情况下将第二个参数中的信息传递给视图,则可以使用 `set_safe` 方法。
从安全角度来看,最好不要使用此方法,但目前似乎没有更好的方法,所以我只能这样做。

 

我想创建一个能够完美应用 Bootstrap 的表单。

我之前写过,如果你忽略一些缺陷,就可以创建一个稍微好一些的表单,
但谁都希望它看起来美观,对吧?!
默认情况下,你可能会看到一个标签和输入元素排列在表格中的表单,但你
可以通过修改模板来控制这种行为。

默认模板是 fuel/core/config/form.php,所以将此文件复制到 app/config/ 并进行修改。

例如,水平表单以下是一个已修改以应用

<?php // fuel/app/config/form.php return [ 'form_template' =>"\n\t\t{打开}\n{字段}\n\t\t{关闭}\n", 'field_template' => "\t\t<div class=\"form-group\"> \n\t\t\t{标签}\n\t\t\t<div class=\"col-xs-3 {error_class}\"> {字段} <span>{描述}</span> {错误消息}</div> \n\t\t</div> \n", 'multi_field_template' => "\t\t<div class=\"form-group\"> \n\t\t\t <label class=\"col-xs-2 control-label\">{group_label}{必填}</label> \n\t\t\t<div class=\"col-xs-3 {error_class}\"> {字段}\n\t\t\t\t<div> {字段} {标签}</div> {字段} <span>{描述}</span> \t\t\t{错误信息}\n\t\t\t</div> \n\t\t</div> \n", 'label_class' => 'col-xs-2 control-label', 'group_label' => '{label}', ];

 
由于混合使用了 \t 和 \n 等特殊字符,格式可能难以理解,但这些字符与屏幕显示无关,因此您可以忽略它们,不会有任何问题。这样做只会使 HTML 源代码略微难以阅读。
此外,有些条目存在于默认的 core/config/form.php 文件中,但不存在于 app/config/form.php 文件中,但这些条目已被合并,并将使用默认设置,因此不会有问题。

基于 Twitter Bootstrap 的AdminLTE可以毫无问题地使用。

 

实际可以减少多少劳动力成本?

首先,数据库设计显然需要(在一定程度上)完善,尤其考虑到模型中信息集中化的必要性。
使用字段集创建屏幕时,无法与数据库设计并行实现,因此应首先专注于完成数据库设计。

此外,虽然研究字段集机制和最佳实践在初期确实花费了一些时间,但经过仔细思考和适应之后,后期完成的速度简直快得惊人,几乎令人陶醉。
事实上,我完成工作时还剩下很多计划内的时间,现在我正利用这些额外的时间来写这篇博客(嘿!)。

如果你还没试过,何不试一试,体验一下它的便捷之处呢?

 
就这样。

如果您觉得这篇文章对您有帮助,请点个“赞”!
2
加载中...
2票,平均分:1.00/12
3,227
X Facebook Hatena书签 口袋

这篇文章的作者

关于作者

万代洋一

我的主要工作是开发社交游戏的Web API,但幸运的是,我也有机会参与其他各种任务,包括市场营销。
我在Beyond中的图像版权采用CC0协议。