sameer-shelavale / x2form
此包旨在简化网页表单的创建、验证和维护。可以直接从MySQL表、Eloquent ORM模型、PHP代码生成HTML表单,如果需要,加载器也可以扩展以支持更多类型的对象。
Requires
- php: >=5.3.0
- sameer-shelavale/multi-captcha: >=1.3.5
This package is not auto-updated.
Last update: 2024-09-24 19:19:09 UTC
README
X2Form是一个用于轻松创建和维护网页表单的表单生成器/构建器。
X2Form架构将表单元素的定义、元素渲染、元素定位(布局/模板)以及表单的处理/验证分离。这使得长期更新和维护表单变得非常容易,添加和删除字段变得极其简单。
##主要功能
- 它可以创建以下类型的网页表单
- Laravel/Eloquent模型或对象。
- MySQL表。
- 通过创建X2Form\Form对象并使用Form类中的add*方法向其中添加元素,可以使用纯PHP调用。
- 表单的XML定义。
- 它可以读取下拉框、复选框和单选按钮的值,这些值来自PHP函数、PHP闭包、PHP全局变量、MySQL查询。
- 支持HTML/PHP模板以自定义表单布局
- 可以处理文件上传,如果发生错误,也可以回滚文件系统更改。
- 它可以根据'datatype'或'datapattern'(使用正则表达式)对表单值进行验证。
- 可以在表单中预填充的值作为数组传递
- 多语言支持,您可以在多种语言中定义标签、工具提示、描述以及错误消息。这使得您的表单能够在多种语言中正确渲染。
- 易于扩展。添加额外的表单元素类型或添加更多类型的加载器、渲染器和模板很容易。
- 干净的命名空间代码
- 使用Composer轻松安装
安装与配置
使用Composer命令
您可以使用Composer在项目命令行中安装X2Form,方法是在项目运行
composer require sameer-shelavale/x2form
composer.json
或者,您可以直接在composer.json文件中的require块中添加它
{
"require": {
"sameer-shelavale/x2form": "2.1.*"
}
}
然后运行composer update
PHP包含
您还可以下载zip/rar存档,解压并将其复制到项目文件夹中适当的位置。然后,在您的代码中包含autoload.php
您还需要下载MultiCaptcha并包含它
include_once( 'PATH-TO-X2FORM-FOLDER/src/autoload.php' );
include_once( 'PATH-TO-MULTICAPTCHA-FOLDER/src/Captcha.php' );
支持的表单控件/元素
X2Form支持以下HTML控件
- 文本
- 多行文本框
- 复选框
- 单选按钮
- 下拉列表
- 文件
- 标签
- 按钮(即
<input type="button" >
) - 提交(即
<input type="submit" >
) - 重置(即
<input type="reset" >
) - 隐藏(即
<input type="hidden" >
) - 图像(即
<input type="image" >
) - 验证码
用法
您可以像这样初始化一个空表单
$form = new \X2Form\Form( 'MyFormName' );
MyFormName是表单的名称
$form = new \X2Form\Form( 'MyFormName', [ 'action' => 'index.php', 'method' => 'post' ] );
参数
表单控件/元素
您可以使用构造函数参数elements,或者初始化表单对象后,您可以使用add*函数或load方法从ORM对象、XML文件、XML字符串或SimpleXML对象中加载元素。首先,我们将看看可用的元素类型以及如何将它们添加到表单中。
文本
此元素在表单中创建一个文本框或<input type="text">
控件
基本参数
高级配置参数:配置属性主要用于表单验证或格式化显示
***重要提示:除了上述所有基本和高级参数外,还可以传递所有其他正常的HTML属性,例如style、class等,适用于<input type="text">
标签。
$form->addText([ 'name'=>'FIRST_NAME', 'label'=>'First Name' ]);
多行文本框
此元素在表单中创建一个<textarea>
控件
基本参数
高级配置参数:配置属性主要用于表单验证或格式化显示
***重要提示:除了上述所有基本和高级参数外,还可以传递所有其他正常的HTML属性,例如style、class等,适用于<textarea>
标签。
$form->addTextarea([ 'name'=>'INTRO', 'label'=>'Write something about yourself', 'rows'=>'5', 'cols'=>'50', 'value'=>'I am Harry... Harry Potter.' ]);
下拉列表
此元素在表单中创建一个<select>
控件
基本参数
高级配置参数:配置属性主要用于表单验证或格式化显示
***重要提示:除了上述所有基本和高级参数外,还可以传递所有其他正常的HTML属性,例如style、class等,适用于<input type="dropdown">
标签。
下拉菜单的基本示例:
$formObj->addDropdown([ 'name'=>'continent', 'label'=>'Continent', 'mandatory' => 'true', 'options'=> [ [ 'value'=>'africa', 'label'=>'Africa' ], [ 'value'=>'america', 'label'=>'America' ], [ 'value'=>'asia', 'label'=>'Asia' ], [ 'value'=>'australia', 'label'=>'Australia' ], [ 'value'=>'europe', 'label'=>'Europe' ], ] );
指定选项
首先,非常重要的是要理解,下拉控件中的每个项目都由value和label组成(对于radio和checkboxes类型也适用)。
如前所述,您可以通过多种方式传递这些值-标签对的组合 1. php数组在这里,您可以简单地传递作为字符串数组的标签和值。例如,让我们看看这个例子,它使用一个简单的1维数组
$formObj->addDropdown([ 'name'=>'continent', 'label'=>'Continent', 'options'=> ['array' => [ 'africa', 'america', 'asia', 'australia', 'europe' ] ], );
当使用1维数组时,每个数组元素都成为值和标签。当值和标签需要不同时,可以使用2维数组,如下所示:
$formObj->addDropdown([ 'name'=>'continent', 'label'=>'Continent', 'mandatory' => 'true', 'options'=> [ [ 'value'=>'afr', 'label'=>'Africa' ], [ 'value'=>'amr', 'label'=>'America' ], [ 'value'=>'asi', 'label'=>'Asia' ], [ 'value'=>'aus', 'label'=>'Australia' ], [ 'value'=>'eur', 'label'=>'Europe' ], ] );
现在可能有这样的情况,您的数组键不是命名为value和label。在这种情况下,您可以指定valuefield和/或labelfield的名称,如下所示。
//here is your 2d array where you don't have value and label keys $customArray = [ [ 'code'=>'afr', 'continent_name'=>'Africa' ], [ 'code'=>'amr', 'continent_name'=>'America' ], [ 'code'=>'asi', 'continent_name'=>'Asia' ], [ 'code'=>'aus', 'continent_name'=>'Australia' ], [ 'code'=>'eur', 'continent_name'=>'Europe' ] ]; $formObj->addDropdown([ 'name'=>'continent', 'label'=>'Continent', 'mandatory' => 'true', 'options'=> [ 'array' => [ 'value' => $continentArray, // here we pass your array 'labelfield' => 'continent_name', // we specify the label field 'valuefield' => 'code', // we specify the value field ] ] );
2. SQL查询:您还可以从SQL查询中加载选项。您需要做的只是传递要运行的查询以及标签和值字段的名称。当然,您应该确保数据库已连接,并且您的表单对象(对于PHP和pdo)中已设置dbHandle。例如,假设您有一个名为'continents'的MySQL表,如下所示:
现在您可以从这个表中创建选项,如下所示:
$formObj->addDropdown([ 'name'=>'continent', 'label'=>'Continent', 'mandatory' => 'true', 'options' => [ 'query' => [ 'sql' => 'SELECT * FROM continents;', // here we pass the query 'labelfield' => 'continent_name', // we specify the label field 'valuefield' => 'code', // we specify the value field ] ] );
或者,您也可以将查询修改为select code as value, continent_name as label from continents;
,您就不必设置labelfield和valuefield。
3. php全局变量:您还可以从PHP全局变量(或全局数组元素的子元素)中加载选项。例如:
//somewhere in your code you set a global variable $GLOBAL['location_data']['continents'] = [ [ 'code'=>'afr', 'continent_name'=>'Africa' ], [ 'code'=>'amr', 'continent_name'=>'America' ], [ 'code'=>'asi', 'continent_name'=>'Asia' ], [ 'code'=>'aus', 'continent_name'=>'Australia' ], [ 'code'=>'eur', 'continent_name'=>'Europe' ] ]; $formObj->addDropdown([ 'name'=>'continent', 'label'=>'Continent', 'mandatory' => 'true', 'options' => [ 'phpglobal' => [ 'var' => 'location_data:continents', // here we pass the continents array from location_data array in $GLOBALS vars 'labelfield' => 'continent_name', // we specify the label field 'valuefield' => 'code', // we specify the value field ] ] );
4. 匿名函数:匿名函数在定义XML表单时很有用,您可以从全局变量/预置中处理它们,并从中创建数据,如下所示:
$continents = [ [ 'code'=>'afr', 'continent_name'=>'Africa' ], [ 'code'=>'amr', 'continent_name'=>'America' ], [ 'code'=>'asi', 'continent_name'=>'Asia' ], [ 'code'=>'aus', 'continent_name'=>'Australia' ], [ 'code'=>'eur', 'continent_name'=>'Europe' ] ]; $formObj->addDropdown([ 'name'=>'continent', 'label'=>'Continent', 'mandatory' => 'true', 'options' => [ 'create_function' => [ 'args' => '$a' 'code' => 'foreach($a as $k => $val ){ $a[$k]["final_name"] = $a[$k]['continent_name']."(".$a[$k]['code'].")"; } return $a;', // the function code 'pass'=> $continents, //we will pass $continents as argument $a to the function we will create 'labelfield' => 'final_name', // we specify the label field 'valuefield' => 'code', // we specify the value field ] ] );
在上面的匿名函数和phpglobals的用法在PHP定义中看起来非常不相关,但在XML中非常有用,因为在那里没有即时的PHP处理。
单选按钮
此元素在表单中创建一个<input type="radio">
控件
基本参数
注意:与上述下拉菜单选项的传递方式相同,可以传递单选控件的选项。
高级配置参数:配置属性主要用于表单验证或格式化显示
***重要提示:除了上述所有基本和高级参数外,还可以传递所有其他正常的HTML属性,例如style、class等,适用于<input type="radio">
标签。单选按钮的基本示例:
$formObj->addRadio([ 'name'=>'gender', 'label'=>'Gender', 'mandatory' => 'true', 'options'=> [ [ 'value'=>'male', 'label'=>'Male' ], [ 'value'=>'female', 'label'=>'Female' ] ] );
复选框
此元素在表单中创建一个<input type="checkbox">
控件
基本参数
高级配置参数:配置属性主要用于表单验证或格式化显示
***重要提示:除了上述所有基本和高级参数外,还可以传递所有其他正常的HTML属性,例如style、class等,适用于<input type="checkbox">
标签。
具有多个选项的复选框示例:
$formObj->addRadio([ 'name'=>'hobbies', 'label'=>'Select your hobbies', 'direction' => 'vertical', 'options'=> [ [ 'value'=>'sports', 'label'=>'Sports' ], [ 'value'=>'music', 'label'=>'Listening music' ], [ 'value'=>'painting', 'label'=>'Drawing & Painting' ], [ 'value'=>'video-games', 'label'=>'Video Games' ] ] );
具有单个选项的复选框示例:
$formObj->addRadio([ 'name'=>'newsletter', 'label'=>'Receive monthly newsletter?', 'direction' => 'vertical', 'options'=> [ [ 'value'=>'yes', 'label'=>'Yes' ] ] );
文件
此元素在表单中创建一个<input type="file">
控件
基本参数
高级配置参数:配置属性主要用于表单验证或格式化显示
***重要提示:除了上述基本和高级参数外,还可以传递所有其他正常的HTML属性,如style、class等,用于<input type="file">
标签。
hidden
此元素在表单中创建一个<input type="hidden">
元素。
基本参数
高级配置参数:配置属性主要用于表单验证或格式化显示。
$form->addHidden([ 'name'=>'product_id', 'value'=> 3, ]);
标签
此元素在表单中创建一个<label>
元素。
基本参数
***重要提示:除了上述参数外,还可以传递所有其他正常的HTML属性,如style、class等,用于<label>
标签。
$form->addLabel([ 'name'=>'LABEL1', 'value'=>'How many matches have you played?', ]);
button
此元素在表单中创建一个<input type="button">
元素。
基本参数
***重要提示:除了上述参数外,还可以传递所有其他正常的HTML属性,如style、class等,用于<input type="button">
标签。
$form->addButton([ 'name'=>'button1', 'value'=>'Calculate', 'class' => 'btn btn-secondary' //these bootstrap classes are optional ]);
submit
此元素在表单中创建一个提交按钮<input type="submit">
。
基本参数
***重要提示:除了上述参数外,还可以传递所有其他正常的HTML属性,如style、class等,用于<input type="button">
标签。
$form->addSubmit([ 'name'=>'button2', 'value'=>'Send', ]);
reset
此元素在表单中创建一个重置按钮<input type="reset">
。
基本参数
***重要提示:除了上述参数外,还可以传递所有其他正常的HTML属性,如style、class等,用于<input type="button">
标签。
$form->addReset([ 'name'=>'button3', 'value'=>'Reset', ]);
image
此元素在表单中创建一个重置按钮<input type="reset">
。
基本参数
***重要提示:除了上述参数外,还可以传递所有其他正常的HTML属性,如style、class等,用于<input type="button">
标签。
$form->addReset([ 'name'=>'button3', 'value'=>'Reset', ]);
验证码
此元素在表单中插入验证码。默认情况下,此元素使用外部包(Multi Captcha)[http://github.com/sameer-shelavale/multi-captcha]来渲染验证码。
基本参数
***重要提示:标签和描述将自动为此字段准备,因此您无需传递它们,如果您传递它们,将忽略它们。
$form->addCaptcha([ 'secret'=>'secret-code-for-this-form', 'options'=> array( 'math'=>[ 'level'=>4 ], 'gif' => [ 'maxCodeLength' => 6, 'width'=>180, 'height'=>60, 'totalFrames'=>50, 'delay'=>20 ] ), 'refreshUrl'=>'your-captcha-refresh-url.php?captcha=refresh', 'helpUrl'=>'http://github.com/sameer-shelavale/multi-captcha' ]);
使用add*函数制作的表单示例
$form = new \X2Form\Form( 'ContactUs', [ 'action' => 'contact-us.php', 'method' => 'post' ] ); $form->addText([ 'name' => 'full_name', 'label' => 'Your Name' ]); $form->addText([ 'name' => 'email', 'label' => 'Email', 'mandatory' => true, 'datatype' => 'email' ]); $form->addTextarea([ 'name' => 'message', 'label' => 'Message', 'mandatory' => true ]); $form->addRadio([ 'name' => 'gender', 'label' => 'Gender', 'options' => [ 'Male', 'Female' ] ]); $form->addCaptcha([ 'name' => 'captcha', 'secret'=>'contact-us-form-secret-blahblah', 'options' => [ 'gif' => [ 'maxCodeLength' => 6, 'width'=>200, 'height'=>80 ] ] ]); $form->addSubmit([ 'name' => 'submit', 'value' => 'Send' ]; $form->finalize(); //prepares the form for rendering, processing, validation etc.
在表单构造函数中指定元素
我们还可以在表单构造函数参数elements中将元素组合在一起。让我们看看如何为简单的“联系我们”表单做到这一点。
$form = new \X2Form\Form( 'ContactUs', [ 'action' => 'contact-us.php', 'method' => 'post' 'elements' => [ [ 'type' => 'text', 'name' => 'full_name', 'label' => 'Your Name' ], [ 'type' => 'text', 'name' => 'email', 'label' => 'Email', 'mandatory' => true, 'datatype' => 'email' ], [ 'type' => 'textarea', 'name' => 'message', 'label' => 'Message', 'mandatory' => true ], [ 'type' => 'radio', 'name' => 'gender', 'label' => 'Gender', 'options' => [ 'Male', 'Female' ] ], [ 'type' => 'captcha', 'name' => 'captcha', 'secret'=>'contact-us-form-secret-blahblah', 'options' => [ 'gif' => [ 'maxCodeLength' => 6, 'width'=>200, 'height'=>80 ] ] ], [ 'type' => 'submit', 'name' => 'submit', 'value' => 'Send' ], ] ] ); $form->finalize(); //prepares the form for rendering, processing, validation etc.
注意:在添加/更新表单字段后,必须运行finalize()函数。
渲染表单。
一旦您完成表单,其他操作都非常简单。要显示表单,您只需执行以下操作
echo $form->render();
请记住,render()函数返回字符串,因此您需要echo它。
处理和验证表单
在您完成表单后,您可以处理提交或验证它。
processSubmission()函数和validate()函数之间有一点区别。validate()函数仅验证数据并返回布尔值作为结果,而不执行其他操作,而processSubmission()函数则验证数据并处理文件上传,即它还将上传的文件移动到目标目录。它返回一个详细的数组日志,包含状态、消息以及错误字段的数组及其相应的错误消息。
if( $_POST['submit'] == "Submit" ){ if( logg_ok( $form->processSubmission( $_POST ) ){ echo "Your data is submitted successfully!"; }else{ //display form again with submitted data populated in it and highlighted error fields echo '<span class="error">'.$form->errorString.'</span>'; echo $form->render(); } }else{ //display form echo $form->render(); }
if( $_POST['submit'] == "Submit" ){ if( $form->validate( $_POST ) ){ //do extra/special validations and server side processing and save data etc. }else{ //display form again with submitted data populated in it and highlighted error fields echo '<span class="error">'.$form->errorString.'</span>'; echo $form->render(); } }else{ //display form echo $form->render(); }
processSubmission()函数
'function processSubmission( $postedData, $oldData, $cancelUploadsOnError = true )'
几乎所有的表单提交处理都可以通过这个函数完成。
参数
$postedData - 它是作为关联数组的提交数据,其中数组键是字段的名称,所以大多数情况下您将传递$_POST作为$postedData
$oldData - 当您编辑现有记录或数据时,需要传递此参数。它主要用于文件处理和表单验证。例如,如果您有一个必填字段PROFILE_PHOTO,即使用户没有上传新文件,如果照片之前已上传,则不应抛出错误。X2Form检查文件是否已上传/存在于$oldData中,如果存在,则不会抛出验证错误。
$cancelUploadsOnError - 该参数表示在发生错误时是否应该删除上传的文件。当然,在您上传多个文件且其中一个上传因上传、移动或验证问题失败的情况下,您可能会遇到这种情况。在这种情况下,我们可能需要回滚文件系统的更改。如果该参数的值为true,则X2Forms会优雅地回滚文件系统的更改。注意。X2Forms会备份它在文件系统中所做的所有更改,并创建备份文件,稍后用于回滚。
返回值 - 返回一个包含 result、code、message、errorFields 的数组
function validate()
'function validate( $postedData, $oldData)'
此函数由processSubmission()函数内部使用。
参数
$postedData - 它是作为关联数组的提交数据,其中数组键是字段的名称,所以大多数情况下您将传递$_POST作为$postedData
$oldData - 当您编辑现有记录或数据时,需要传递此参数。它主要用于文件处理和表单验证。例如,如果您有一个必填字段PROFILE_PHOTO,即使用户没有上传新文件,如果照片之前已上传,则不应抛出错误。X2Form检查文件是否已上传/存在于$oldData中,如果存在,则不会抛出验证错误。
返回值 - 在成功验证时返回(boolean) true,或在失败时返回false
注意:无论您将什么$ postedData传递给processSubmission()和validate()函数,它都会填充到表单中。此外,这些函数通过设置该字段(元素)的errorString属性来标记有错误的字段,这些字段将具有额外的css类errorfield。它还设置'$form->errorString',其中包含验证过程中发生的错误摘要。
使用ajax刷新元素
使用如bootstrap等框架渲染表单和表单元素
默认情况下,X2Form以表格格式渲染表单,即使用<table>
、<tr>
和<td>
标签。您也可以通过将渲染器设置为bootstrap渲染器对象来渲染它,是的,就是这样。例如
$form = new \X2Form\Form( 'MyFormName', [ 'action' => 'index.php', 'method' => 'post', 'renderer' => new X2Form\Renderers\Bootstrap\Renderer() //this is all you need to render in bootstrap ] );
注意:目前它仅支持table和bootstrap渲染器;我们计划在未来添加jqueryui和angular渲染器。然而,您仍然可以扩展当前渲染器或实现自己的。请记住,渲染器必须实现X2Form\Interfaces\Renderer接口。
使用模板自定义表单布局和元素定位
有时您不想使用表单的默认两列垂直布局,并希望对表单中单个字段的定位有更多控制。按钮也可能一个接一个地出现。(也许我应该在未来添加一个button-group类型)
在这种情况下,模板非常有用,使用模板,您可以按需组织表单和定位元素。
X2Form模板是一个普通的html/php文件,<body>
和</body>
标签内的所有数据都用作表单模板,html的<head>
部分被丢弃,这允许您使用任何html编辑器快速制作模板。
要将表单元素放置在模板中,只需在该位置写入文本[ELEMENTNAME],这里的ELEMENTNAME是元素的name。
渲染后,[ELEMENTNAME]将被实际元素的html替换。
因此,对于FIRST_NAME,我们可以放入[FIRST_NAME]
类似地,要将元素的标签放置在模板中,请放入[FIRST_NAME_label],注意这里的后缀_label,要显示描述,请使用[FIRST_NAME_description]。
在进行所有这些操作时,请记住,您必须不在模板中指定<FORM>
标签,渲染器会自动在模板数据周围放置<form>
标签。
*特别感谢JetBrains(http://www.jetbrains.com)为此项目提供免费的jetBrains PHPStorm IDE许可证,并对开源社区的持续支持。