此包旨在简化网页表单的创建、验证和维护。可以直接从MySQL表、Eloquent ORM模型、PHP代码生成HTML表单,如果需要,加载器也可以扩展以支持更多类型的对象。

v2.1.1 2016-07-20 17:01 UTC

README

X2Form是一个用于轻松创建和维护网页表单的表单生成器/构建器。

X2Form架构将表单元素的定义、元素渲染、元素定位(布局/模板)以及表单的处理/验证分离。这使得长期更新和维护表单变得非常容易,添加和删除字段变得极其简单。

##主要功能

  1. 它可以创建以下类型的网页表单
  • Laravel/Eloquent模型或对象。
  • MySQL表。
  • 通过创建X2Form\Form对象并使用Form类中的add*方法向其中添加元素,可以使用纯PHP调用。
  • 表单的XML定义。
  1. 它可以读取下拉框、复选框和单选按钮的值,这些值来自PHP函数、PHP闭包、PHP全局变量、MySQL查询。
  2. 支持HTML/PHP模板以自定义表单布局
  3. 可以处理文件上传,如果发生错误,也可以回滚文件系统更改。
  4. 它可以根据'datatype'或'datapattern'(使用正则表达式)对表单值进行验证。
  5. 可以在表单中预填充的值作为数组传递
  6. 多语言支持,您可以在多种语言中定义标签、工具提示、描述以及错误消息。这使得您的表单能够在多种语言中正确渲染。
  7. 易于扩展。添加额外的表单元素类型或添加更多类型的加载器、渲染器和模板很容易。
  8. 干净的命名空间代码
  9. 使用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属性,例如styleclass等,适用于<input type="text">标签。

$form->addText([
    'name'=>'FIRST_NAME',
    'label'=>'First Name'
]);

多行文本框

此元素在表单中创建一个<textarea>控件

基本参数

高级配置参数:配置属性主要用于表单验证或格式化显示

***重要提示:除了上述所有基本和高级参数外,还可以传递所有其他正常的HTML属性,例如styleclass等,适用于<textarea>标签。

$form->addTextarea([
    'name'=>'INTRO',
    'label'=>'Write something about yourself',
    'rows'=>'5',
    'cols'=>'50',
    'value'=>'I am Harry... Harry Potter.'
]);

下拉列表

此元素在表单中创建一个<select>控件

基本参数

高级配置参数:配置属性主要用于表单验证或格式化显示

***重要提示:除了上述所有基本和高级参数外,还可以传递所有其他正常的HTML属性,例如styleclass等,适用于<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' ],
    ]
);

指定选项

首先,非常重要的是要理解,下拉控件中的每个项目都由valuelabel组成(对于radiocheckboxes类型也适用)。

如前所述,您可以通过多种方式传递这些值-标签对的组合 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' ],
    ]
);

现在可能有这样的情况,您的数组键不是命名为valuelabel。在这种情况下,您可以指定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属性,例如styleclass等,适用于<input type="radio">标签。单选按钮的基本示例:

$formObj->addRadio([
    'name'=>'gender',
    'label'=>'Gender',
    'mandatory' => 'true',
    'options'=> [
        [ 'value'=>'male', 'label'=>'Male' ],
        [ 'value'=>'female', 'label'=>'Female' ]
    ]
);

复选框

此元素在表单中创建一个<input type="checkbox">控件

基本参数

高级配置参数:配置属性主要用于表单验证或格式化显示

***重要提示:除了上述所有基本和高级参数外,还可以传递所有其他正常的HTML属性,例如styleclass等,适用于<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属性,如styleclass等,用于<input type="file">标签。

hidden

此元素在表单中创建一个<input type="hidden">元素。

基本参数

高级配置参数:配置属性主要用于表单验证或格式化显示。

$form->addHidden([
    'name'=>'product_id',
    'value'=> 3,
]);

标签

此元素在表单中创建一个<label>元素。

基本参数

***重要提示:除了上述参数外,还可以传递所有其他正常的HTML属性,如styleclass等,用于<label>标签。

$form->addLabel([
    'name'=>'LABEL1',
    'value'=>'How many matches have you played?',
]);

button

此元素在表单中创建一个<input type="button">元素。

基本参数

***重要提示:除了上述参数外,还可以传递所有其他正常的HTML属性,如styleclass等,用于<input type="button">标签。

$form->addButton([
    'name'=>'button1',
    'value'=>'Calculate',
    'class' => 'btn btn-secondary' //these bootstrap classes are optional
]);

submit

此元素在表单中创建一个提交按钮<input type="submit">

基本参数

***重要提示:除了上述参数外,还可以传递所有其他正常的HTML属性,如styleclass等,用于<input type="button">标签。

$form->addSubmit([
    'name'=>'button2',
    'value'=>'Send',
]);

reset

此元素在表单中创建一个重置按钮<input type="reset">

基本参数

***重要提示:除了上述参数外,还可以传递所有其他正常的HTML属性,如styleclass等,用于<input type="button">标签。

$form->addReset([
    'name'=>'button3',
    'value'=>'Reset',
]);

image

此元素在表单中创建一个重置按钮<input type="reset">

基本参数

***重要提示:除了上述参数外,还可以传递所有其他正常的HTML属性,如styleclass等,用于<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会备份它在文件系统中所做的所有更改,并创建备份文件,稍后用于回滚。

返回值 - 返回一个包含 resultcodemessageerrorFields 的数组

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
    ]
);

注意:目前它仅支持tablebootstrap渲染器;我们计划在未来添加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许可证,并对开源社区的持续支持。