【发布时间】:2008-11-13 22:44:19
【问题描述】:
我将如何创建一个真实世界的表单创建类,我可以使用它来显示具有不同类型字段的新表单,我想要多少个字段,我可以使用下拉菜单,我可以通过使用 OOP?
【问题讨论】:
我将如何创建一个真实世界的表单创建类,我可以使用它来显示具有不同类型字段的新表单,我想要多少个字段,我可以使用下拉菜单,我可以通过使用 OOP?
【问题讨论】:
说实话,考虑到有一些成熟的 PHP 表单包,我不会自己推出。
我将 PEAR 的 HTML_QuickForm 包 (http://pear.php.net/manual/en/package.html.html-quickform.php) 用于 PHP4 网站。
对于 PHP5,我会查看 Zend_Form (http://framework.zend.com/manual/en/zend.form.html)。
对于我的快速表单代码,我使用了一个帮助类,它允许我使用配置数组定义表单。例如:
echo QuickFormHelper::renderFromConfig(array(
'name' => 'area_edit',
'elements' => array(
'area_id' => array('type' => 'hidden'),
'active' => array('type' => 'toggle'),
'site_name' => array('type' => 'text'),
'base_url' => array('type' => 'text'),
'email' => array('type' => 'text'),
'email_admin' => array('type' => 'text'),
'email_financial' => array('type' => 'text'),
'cron_enabled' => array('type' => 'toggle'),
'address' => array('type' => 'address'),
),
'groups' => array(
'Basic Details' => array('site_name', 'base_url'),
'Address Details' => array('address'),
'Misc Details' => array(), // SM: Display the rest with this heading.
),
'defaults' => $site,
'callback_on_success' => array(
'object' => $module,
'function' => 'saveSite',
),
));
请注意,上述元素类型“地址”和“切换”实际上是多个表单字段(基本上,元类型)。这就是我喜欢这个助手类的地方——我可以用它们的规则(例如地址、信用卡等)定义一组标准的字段,并且它们可以以一致的方式在许多页面上使用。
【讨论】:
你绝对可以。考虑一个存储表单本身信息的 Form 类:method、action、enctype 属性。还可以在顶部添加可选标题和/或描述文本等内容。当然,您还需要一个输入元素数组。这些可能会被放入它们自己的类中(尽管为 InputText、InputCheckbox、InputRadio 子类化它们可能有点过分)。这是一个模糊的骨架设计:
class Form {
var $attributes, // array, with keys ['method' => 'post', 'action' => 'mypage.php'...]
$heading,
$description,
$inputs // array of FormInput elements
;
function render() {
$output = "<form " . /* insert attributes here */ ">"
. "<h1>" . $this->heading . "</h1>"
. "<p>" . $this->description . "</p>"
;
// wrap your inputs in whatever output style you prefer:
// ordered list, table, etc.
foreach ($this->inputs as $input) {
$output .= $input->render();
}
$output .= "</form>";
return $output;
}
}
FormInput 类只需要存储基本信息,例如类型、名称、值、标签。如果你想变得棘手,那么你可以应用验证规则,然后在渲染时将其转换为 Javascript。
【讨论】:
我将在这里反对其他建议,并建议您构建自己的库来生成表单。如果你失败了,你仍然会在这个过程中学到很多东西。
设计过程在这里是最重要的。您从顶部开始,并问自己表格上的内容。在抽象层面上,一个表格充满了元素。有些是可见的,有些不可见,有些可以由用户输入,但有些不能,有些元素可以触发其他元素……不胜枚举……
最终你会得到“装饰性”元素(文本、标题、分隔符、字段集、链接、图像)、交互式元素(输入、下拉菜单、复选框、单选按钮、提交按钮),最后是既不是装饰性的,也不是交互性的(隐藏的输入、锚点和作为容器对其他元素进行分组的元素。)
一旦您组织好不同的类别,您就可以开始研究所有元素都具有的特性,并且可以将其放入基本元素类中。然后你沿着链条上去,让你的类做更多的事情,从其他更简单的元素类继承。在我的库中,基本元素类称为 form_element ,每个 form_element 都有一个唯一的名称,同一表单中的其他元素都不能拥有。 form_element 也有一组属性。它有一个所有元素都调用的函数render()。在基类中 render() 什么都不做(所以基元素总是不可见的),但在派生类中它开始生成 HTML。顺便说一句,我从来没有让我的任何课程创建 HTML。相反,我有一个名为 html 的静态类,它为所有需要其服务的类编写 HTML。
在表单元素链的早期,您应该有一个,一个将其他元素分组的容器。它应该有一个 add() 函数,它的 render() 函数应该包括调用它所有子元素的 render() 函数。表单类将从这个容器类派生。
在设计上花费大量时间。注意与库的其余部分的兼容性。
如果您希望表单中的数据来自数据库并保存到一个数据库中,您将需要添加此功能并将表单元素类链接到表和列。在这里,我也有一个单独的数据库类,可以检索/保存数据。我有一个创建查询的查询类。表单元素应该与创建 HTML、创建查询或访问数据库无关。我的静态类 DB 和我的查询类负责处理繁琐的工作。表单类应该只涉及表单内容。表单类将需要保存的字段的所有表和列收集到一个数组中,并将其传递给创建查询的查询类,然后将查询传递给执行它的 DB 类。
一旦您正确设置,使用正确设计的类,看似极其复杂的事情突然变得非常容易。
因为您有一个可以编写 HTML 的类,所以您的表单类只需要 html::init() 并在其后使用 render() 并且表单的整个 HTML 代码都在 html 缓冲区中可用。 html::output() 刷新所有内容。
验证也通过静态验证类在外部处理。可以验证的表单元素以可以直接传递给验证类的格式在数组中保存验证指令。每个需要验证的元素都绑定到一个错误元素,如果元素未验证,则显示错误,或者如果一切顺利,则保持不可见。
这是为了向您展示,当您设计表单环境(或其他任何东西)时,您确实需要在开始之前绝对考虑所有事情。您投入其中的工作可能不会立即转化为可以为您的应用程序提供动力的代码,但它肯定会让您成为更好的开发人员,从而使您未来的项目更容易处理。
form 类创建表单,html 类创建 HTML,query 类进行查询,DB 类处理数据库。如果你的类开始做应该由单独的类完成的工作,那么你就有了设计问题。
这是一个代码示例,展示了我的表单库是如何工作的:
$fm = new form('myform');
$fm->binding(FORM_DATABASE);
$fm->state(FORM_RETRIEVE);
$fm->set_recno(1);
$fm->add(new form_heading("My form"));
$fm->add($el=new form_input("name",40));
$el->bind_data('mytable','mycolumn');
$el->set_attribute('size', 25);
$el->set_default('Name');
$fm->add($el=new form_submit("submit_btn","Submit"));
if($fm->manage())
{
redirect or do something else here. The interaction with the form is done. The initial state for the form was FORM_RETRIEVE. If it had been FORM_NEW it would have displayed default values instead of the retrieved record and saved the form as a new record in the table.
}
请注意,表单的 manage() 函数会处理所有事情,从数据库中检索数据,将表单呈现到视图中,验证数据并将其保存回数据库。
以编程方式(如上所述)创建表单的优点之一是可以选择编写自己的基于表单的代码生成器来创建代码来制作表单。
我希望这可以帮助你或其他人。
【讨论】:
仅供参考,Khurram Khan 的Object Oriented Forms 是一个优秀的 PHP OO 表单实现。
下面是代码示例:
$form = new Form("Register", "form.php");
$personal = new Block("Personal Information");
$name = new Text("name", "Your name");
$name->setDescription("this is my description");
$name->addValidator(new MaxLengthValidator("The name you have entered is too long", 30));
...
另一个更流行的实现是PHPlib。但是,我觉得这有点笨拙。看起来它只是封装在一个类中的一些标准函数式编程。
另一种选择是为内置的DOM 库编写抽象。这将允许您使用 OO 表示法手动创建任何类型的表单和表单元素,另外还有一个好处是您将返回一个 OO DOM 实例,该实例可以在程序的其他地方使用。
【讨论】:
您绝对应该使用 OO PHP 来处理表单,以及所有其他的 HTML 输出。我找不到任何 PHP 库(这些答案中的许多链接都已失效)来做我想做的事,所以我写了PHPFUI。它不是一个通用的 HMTL 输出库,而是为Foundation CSS Framework 输出页面。您可以轻松地使用相同的技术来输出更普通的页面、Bootstrap 或其他任何东西。我不想编写一个通用的 HTML OO PHP 库,因为出于性能原因,我想要一些精简的东西。另外我不喜欢过度设计东西,所以它被硬编码到 Foundation 中。但同样的原则也适用于任何希望输出干净的 HTML 且没有验证问题的 PHP 库,您经常会在手写 HTML 中找到这些问题。
【讨论】: