PHP Form Class
Complete documentation with code examples

The PHP Form class is the core of the system.
Instantiate your forms by creating an object with $form = new Form();.
Then add your fields and render the HTML code with the help of the functions detailed in this document.

Overview

To build and display your form, you have to include four PHP code blocks:

  1. The first block at the very beginning of your page to include Form.php and build the form.
  2. The second block in your <head></head> section to call required css files for plugins.
  3. The third block in <body></body> section to render your form.
  4. The fourth block just before </body> to call required js files and js code to activate plugins.

Here is an example of a page containing a form:

<?php
/*============================================
=            1st block - the form            =
============================================*/

use phpformbuilder\Form;
use phpformbuilder\Validator\Validator;

// Start the PHP session
session_start();

// Include the main Form class
include_once rtrim($_SERVER['DOCUMENT_ROOT'], DIRECTORY_SEPARATOR) . '/phpformbuilder/Form.php';

// Create the form
$form = new Form('test-form', 'horizontal', 'novalidate');

// Call functions to add fields and elements
$form->addInput('text', 'user-name', '', 'Name :', 'required, placeholder=Name');
$form->addRadio('is-all-ok', 'Yes', 1);
$form->addRadio('is-all-ok', 'No', 0);
$form->printRadioGroup('is-all-ok', 'Is all ok ?', false, 'required');
$form->addBtn('submit', 'submit-btn', 1, 'Send', 'class=btn btn-success');

// iCheck plugin
$form->addPlugin('icheck', 'input', 'default', array('%theme%' => 'square', '%color%' => 'red'));

/*===========  End of 1st block  ============*/
?>
<!DOCTYPE html>
<html>
    <head>
    <title>Test Form</title>

    <!-- Bootstrap 5 CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">

    <?php
    /*============================================================
    =            2nd block - css includes for plugins            =
    ============================================================*/

    $form->printIncludes('css');

    /*===================  End of 2nd block  ====================*/
    ?>
</head>
<body>
    <h1>My first form</h1>
    <?php
    /*======================================================================================================
    =            3rd block - render the form and the feedback message if the form has been sent            =
    ======================================================================================================*/

    if (isset($sent_message)) {
        echo $sent_message;
    }
    $form->render();

    /*========================================  End of 3rd block  =========================================*/
    ?>

    <!-- Bootstrap 5 JavaScript -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>

    <?php
    /*========================================================================
    =            4th block - js includes for plugins and js code (domready)  =
    ========================================================================*/

    $form->printIncludes('js');
    $form->printJsCode();

    /*=========================  End of 4th block ===========================*/
    ?>
</body>
</html>

Frameworks

All options are ready to use and will generate HTML markup according to the chosen framework.

The default framework is Bootstrap 5.

If none of the available frameworks powers your website, we provide a minimal version of Bootstrap 5 CSS to design your forms.

Bootstrap 4

$form = new Form('my-form', 'horizontal', 'novalidate', 'bs4');

Bootstrap 5 Default

$form = new Form('my-form', 'horizontal', 'novalidate');

Bulma

$form = new Form('my-form', 'horizontal', 'novalidate', 'bulma');

Foundation - v6.4 or higher, with XY grid

$form = new Form('my-form', 'horizontal', 'novalidate', 'foundation');

Material Design

Material Design forms are built with Materialize framework.

Pages created with Materialize or Bootstrap 4 can both include Material Design forms.

  • If your website uses Materialize framework:
    $form = new Form('my-form', 'horizontal', 'novalidate', 'material');
  • If your website uses Bootstrap 4 framework:
    $form = new Form('my-form', 'horizontal', 'novalidate', 'material');
    
    // materialize plugin
    $form->addPlugin('materialize', '#my-form');

Tailwind

$form = new Form('my-form', 'horizontal', 'novalidate', 'tailwind');

UIKit

$form = new Form('my-form', 'horizontal', 'novalidate', 'uikit');

No framework

Add the minimal Bootstrap 5 CSS to your page head, then you can build your forms with Bootstrap 5.

This style sheet only includes what is necessary to layout your responsive forms and will not break anything in the other parts of your pages.

<head>
    // link to the minimal Bootstrap 5 CSS
    <link rel="stylesheet" href="/phpformbuilder/templates/assets/bootstrap5-phpfb/css/bootstrap5-phpfb.min.css">
</head>
<?php
// Then you can build your form
$form = new Form('my-form', 'horizontal', 'novalidate');

More details about __construct() here: Main functions > General > Construct

About optimization (CSS & JS dependencies)

Without PHP Form Builder, your page loads the plugin dependencies (CSS and JavaScript files) one by one.
For instance, if your form uses five plugins, you will need to call at least ten files (5 CSS + 5 JavaScript),
which considerably increases the loading time.

PHP Form Builder groups and compresses all the CSS and JavaScript dependencies into a single CSS | JavaScript file.

Your page will, therefore, only call two dependency files. Efficiency is maximum, no matter how many plugins you use.

JavaScript dependencies can also be loaded with the excellent loadjs library.

Detailed explanations are available here: Optimization (CSS & JS dependencies)

Options

Overview

The PHP Form Builder options define the containers and various HTML elements your forms will use.
The Default options are for use with Bootstrap 5.
Each can be overwritten the way you want to match other framework

For example, with Bootstrap, each group (label + element) has to be wrapped into a <div class="form-group"></div> and to have a .form-control class

We also need do add .col-sm-x & .control-label to labels,
and to wrap elements with <div class="col-sm-x"></div>.

The form options allow us to configure it all efficiently.

If needed, wrappers can contain two HTML elements.
It can be done with elementsWrapper, checkboxWrapper, and radioWrapper.

To add an input wrapper, see the addInputWrapper function.

Default options (Bootstrap 5)

$bs5_options = array(
'formHorizontalClass'          => 'form-horizontal',
'formVerticalClass'            => '',
'elementsWrapper'              => '<div class="bs5-form-stacked-element mb-3"></div>',
'checkboxWrapper'              => '<div class="form-check"></div>',
'radioWrapper'                 => '<div class="form-check"></div>',
'helperWrapper'                => '<span class="form-text"></span>',
'buttonWrapper'                => '<div class="mb-3"></div>',
'wrapElementsIntoLabels'       => false,
'wrapCheckboxesIntoLabels'     => false,
'wrapRadiobtnsIntoLabels'      => false,
'elementsClass'                => 'form-control',
'wrapperErrorClass'            => '',
'elementsErrorClass'           => 'is-invalid',
'textErrorClass'               => 'invalid-feedback w-100 d-block',
'verticalLabelWrapper'         => false,
'verticalLabelClass'           => 'form-label',
'verticalCheckboxLabelClass'   => 'form-label',
'verticalRadioLabelClass'      => 'form-label',
'horizontalLabelWrapper'       => false,
'horizontalLabelClass'         => 'col-form-label',
'horizontalLabelCol'           => 'col-sm-4',
'horizontalOffsetCol'          => 'col-sm-offset-4',
'horizontalElementCol'         => 'col-sm-8',
'inlineCheckboxLabelClass'     => 'form-check-label',
'inlineRadioLabelClass'        => 'form-check-label',
'inlineCheckboxWrapper'        => '<div class="form-check form-check-inline"></div>',
'inlineRadioWrapper'           => '<div class="form-check form-check-inline"></div>',
'iconBeforeWrapper'            => '<div class="input-group-text"></div>',
'iconAfterWrapper'             => '<div class="input-group-text"></div>',
'btnGroupClass'                => 'btn-group',
'requiredMark'                 => '<sup class="text-danger">* </sup>',
'openDomReady'                 => 'document.addEventListener(\'DOMContentLoaded\', function(event) {',
'closeDomReady'                => '});'
);

Example of generated HTML code for each option

The table below shows the correspondence between the options and the generated HTML code. The values of the options are arbitrary, used simply to illustrate the examples.

formHorizontalClass <form class="form-horizontal" [...]>
formVerticalClass <form class="form-vertical" [...]>
elementsWrapper <div class="row mb-3">
[<label> ... </label>]
[<input>]
</div>
checkboxWrapper <div class="form-check">
[<label>]
[<input type="checkbox">[text]]
[</label>]
</div>
radioWrapper <div class="form-check">
[<label>]
[<input type="radio">]
[</label>]
</div>
helperWrapper <span class="form-text">[Help text]</span>
buttonWrapper <div class="mb-3">
[<label> ... </label>]
[<button> ... </button>]
</div>
wrapElementsIntoLabels (if true) <label>[input | textarea | ...]</label>
wrapCheckboxesIntoLabels (if true) <label>[checkbox]</label>
wrapRadiobtnsIntoLabels (if true) <label>[radio]</label>
elementsClass <input class="form-control" [...]>
wrapperErrorClass <div class="[form-group] has-error">
elementsErrorClass <input class="[form-control] error-class" [...]>
textErrorClass <p class="text-danger"> ... </p>
verticalLabelWrapper if true, the labels will be wrapped in a <div class="verticalLabelClass">
verticalLabelClass <div class="verticalLabelClass">[label]</div>
verticalCheckboxLabelClass <label for="[fieldname]" class="verticalCheckboxLabelClass">[text]</label>
verticalRadioLabelClass <label for="[fieldname]" class="verticalRadioLabelClass">[text]</label>
horizontalLabelWrapper if true, the labels will be wrapped in a div with the column class instead of having the column class themselves
horizontalLabelClass,
horizontalLabelCol
<label class="col-sm-4 control-label">...</label>
horizontalOffsetCol // when label is empty, automaticaly offsetting field container
<div class="col-sm-offset-4 [col-sm-8]">
[<input>]
</div>
horizontalElementCol <div class="col-sm-8">
[<input>]
</div>
inlineCheckboxLabelClass <label class="checkbox-inline">...</label>
inlineRadioLabelClass <label class="radio-inline">...</label>
inlineCheckboxWrapper <div class="form-check form-check-inline">
[input type="checkbox"]
[label]
</div>
inlineRadioWrapper <div class="form-check form-check-inline">
[input type="radio"]
[label]
</div>
iconBeforeWrapper <div class="input-group-text icon-before">[input with addon]</div>
iconAfterWrapper <div class="input-group-text icon-after">[input with addon]</div>
btnGroupClass <div class="btn-group">...</div>
requiredMark // required markup is automaticaly added on required fields
<label>my required text<sup class="text-danger"> *</sup></label>
openDomReady document.addEventListener(\'DOMContentLoaded\', function(event) {
closeDomReady });

Customizing for another framework

You can use PHP Form Builder with any framework, e.g., Semantic-UI, Pure, Skeleton, UIKit, Milligram, Susy, Bulma, Kube, etc.

You simply have to change the options to match your framework HTML & CSS classes:

$options = array(
    // your options here
);

$form->setOptions($options);

If you always use the same framework, the best way is to create a custom function with your custom config in the FormExtended class.

Main functions - General

construct

$form = new Form($form_ID, $layout = 'horizontal', $attr = '', $framework = 'bs5');
    /**
     * Defines the layout (horizontal | vertical).
     * Default is 'horizontal'
     * Clears values from the PHP session if self::clear has been called before
     * Catches posted errors
     * Adds hidden field with the form ID
     * Sets elements wrappers
     *
     * @param string $form_ID   The ID of the form
     * @param string $layout    (Optional) Can be 'horizontal' or 'vertical'
     * @param string $attr      (Optional) Can be any HTML input attribute or js event EXCEPT class
     *                          (class is defined in layout param).
     *                          attributes must be listed separated with commas.
     *                          Example : novalidate,onclick=alert(\'clicked\');
     * @param string $framework (Optional) bs4 | bs5 | bulma | foundation | material | tailwind | uikit
     *                          (Bootstrap 4, Bootstrap 5, Bulma, Foundation, Material design, Tailwind, UIkit
     * @return $this
     */

options

Call setOptions() only if you change defaults options

Go to Options for more details

$form->setOptions($options);
    /**
    * Sets form layout options to match your framework
    * @param array $user_options (Optional) An associative array containing the
    *                            options names as keys and values as data.
    */

Mode (production vs. development)

Default mode is production.

$form->setMode($mode);
    /**
     * set the form mode to 'development' or 'production'
     * in production mode, all the plugins dependencies are combined and compressed in a single css or js file.
     * the css | js files are saved in plugins/min/css and plugins/min/js folders.
     * these 2 folders have to be wrirable (chmod 0755+)
     * @param string $mode 'development' | 'production'
     * @return $this
     */

Detailed explanations available here: Optimization (CSS & JS dependencies)

Method

The default method is POST.

Call setMethod() only if you change default method

$form->setMethod($method);
    /**
    * set sending method
    * @param string $method POST|GET
    */

Action

Default action is htmlspecialchars($_SERVER["PHP_SELF"]).

htmlspecialchars prevents attackers from exploiting the code by injecting HTML or JavaScript code (Cross-site Scripting attacks) in forms (recommended on http://www.w3schools.com/php/php_form_validation.asp)

Call setAction() only if you change default action

$form->setAction($url, [$add_get_vars = true]);
    /**
    * Redefines form action
    *
    * @param boolean $add_get_vars (Optional) if $add_get_vars is set to false,
    *                              url vars will be removed from destination page.
    *                              Example: www.myUrl.php?var=value => www.myUrl.php
    */

Start Fieldset

Start your fieldset with an optional legend.
Don't forget to call endFieldset to end your fieldset.

You can add several fieldsets on the same form.

$form->startFieldset('legend', $fieldset_attr = '', $legend_attr = '');
    /**
    * Starts a fieldset tag.
    * @param string $legend (Optional) Legend of the fieldset.
    * @param string $fieldset_attr (Optional) Fieldset attributes.
    * @param string $legend_attr (Optional) Legend attributes.
    */

End Fieldset

$form->endFieldset();
    /**
    * Ends a fieldset tag.
    */

startDependentFields

Start a dependent fields block.
The dependent fields block is hidden and will be shown if $parent_field changes to one of $show_values.
Don't forget to call endDependentFields to end your Dependent Fields block.

if $inverse is true, dependent fields will be shown if any other value than $show_values is selected

Each Dependent fields block can include one or several dependent fields blocks.

Dependent fields MUST NOT START with the same fieldname as their parent field.

$form->startDependentFields($parent_field, $show_values[, $inverse = false]);
    /**
    * Start a hidden block
    * which can contain any element and html
    * Hiden block will be shown on $parent_field change
    * if $parent_field value matches one of $show_values
    * @param  string $parent_field name of the field which will trigger show/hide
    * @param  string $show_values  single value or comma separated values which will trigger show.
    * @param  boolean $inverse  if true, dependent fields will be shown if any other value than $show_values is selected.
    * @return void
    */

Live examples with code are available here: javascript-plugins.php#dependent-fields-example

endDependentFields

$form->endDependentFields();
    /**
    * Ends Dependent Fields block.
    */

$attr argument

Several element functions use a $attr argument.

The $attr argument accepts any HTML attribute or javascript event.

Use comma-separated values (see examples below).

Examples

    $form->addInput('text', 'name', '', 'Your name: ', 'id=my-id, placeholder=My Text, required=required');
    $form->addInput('password', 'pass', '', 'Your password: ', 'required=required, pattern=(.){7\,15}');
    $form->addTextarea('my-textarea', '', 'Your message: ', 'cols=30, rows=4');
    $form->addBtn('button', 'myBtnName', 1, 'Cancel', 'class=btn btn-danger, onclick=alert(\'cancelled\');');

Elements

Input

$form->addInput($type, $name [, $value = '', $label = '', $attr = '']);
    /**
    * Adds input to the form
    *
    * @param string $type Accepts all input html5 types except checkbox and radio:
    *                      button, color, date, datetime, datetime-local,
    *                      email, file, hidden, image, month, number, password,
    *                      range, reset, search, submit, tel, text, time, url, week
    * @param string $name The input name
    * @param string $value (Optional) The input default value
    * @param string $label (Optional) The input label
    * @param string $attr (Optional) Can be any HTML input attribute or js event.
    *                                attributes must be listed separated with commas.
    *                                If you don't specify any ID as attr, the ID will be the input's name.
    *                                Example: class=my-class,placeholder=My Text,onclick=alert(\'clicked\');
    */

Textarea

$form->addTextarea($name, $value [, $label, $attr]);
    /**
    * Adds textarea to the form
    * @param string $name             The textarea name
    * @param string $value (Optional) The textarea default value
    * @param string $label (Optional) The textarea label
    * @param string $attr (Optional)  Can be any HTML input attribute or js event.
    *                                 attributes must be listed separated with commas.
    *                                 If you don't specify any ID as attr, the ID will be the name of the textarea.
    *                                 Example: cols=30, rows=4;.
    */

Options for Select list

Always add your options BEFORE creating the select element

  1. 1 Add your options
  2. 2 Create your select
$form->addOption($selectName, $value, $txt [, $group_name, $attr]);
    /**
    * Adds option to the $select_name element
    *
    * @param string $select_name The name of the select element
    * @param string $value The option value
    * @param string $txt The text that will be displayed
    * @param string $group_name (Optional) the optgroup name
    * @param string $attr (Optional) Can be any HTML input attribute or js event.
    *                                attributes must be listed separated with commas.
    *                                If you don't specify any ID as attr, the ID will be the option's name.
    *                                Example: class=my-class
    */

Select list

$form->addSelect($selectName, $label [, $attr = '', $displayGroupLabels = true]);

addSelect() function plays nice with bootstrap-select plugin and select2 plugin.

Add the selectpicker class for Bootstrap select or the select2 class for the Select2 plugin, data-attributes and phpformbuilder will do the job.

Don't forget to activate your plugins to add the required css/js files to your page.

    /**
    * Adds a select element
    *
    * IMPORTANT: Always add your options BEFORE creating the select element
    *
    * @param string $select_name The name of the select element
    * @param string $label (Optional) The select label
    * @param string $attr (Optional)  Can be any HTML input attribute or js event.
    *                                 attributes must be listed separated with commas.
    *                                 If you don't specify any ID as attr, the ID will be the input's name.
    *                                 Example: class=my-class
    * @param string $displayGroupLabels (Optional) True or false.
    *                                              Default is true.
    */

Example with optgroup

    $form->addOption('select-with-groupnames', 'option-1', 'option 1', 'group 1');
    $form->addOption('select-with-groupnames', 'option-2', 'option 2', 'group 1', 'selected=selected');
    $form->addOption('select-with-groupnames', 'option-3', 'option 3', 'group 1');
    $form->addOption('select-with-groupnames', 'option-4', 'option 4', 'group 2');
    $form->addOption('select-with-groupnames', 'option-5', 'option 5', 'group 2');
    $form->addSelect('select-with-groupnames', 'Select please: ', '');

Example with multiple selections

    for ($i=1; $i < 11; $i++) {
        $form->addOption('myMultipleSelectName[]', $i, 'option ' . $i);
    }
    $form->addSelect('myMultipleSelectName[]', 'Select please:
(multiple selections)', 'multiple=multiple');

Country Select list

The addCountrySelect() function generates a full country select dropdown list with all the countries options. Fortunately, you don't have to add the options one by one. The function does it for you.

You can choose your prefered plugin, which can be slimselect (default), bootstrap-select or select2.

If you choose the bootstrap-select plugin keep in mind that it requires Bootstrap's dropdown in your bootstrap.min.js

$form->addCountrySelect($select_name [, $label = '', $attr = '', $user_options = array()]);
    /**
    * adds a country select list with flags
    * @param array  $select_name
    * @param string $label        (Optional) The select label
    * @param string $attr         (Optional)  Can be any HTML input attribute or js event.
    *                             attributes must be listed separated with commas.
    *                             If you don't specify any ID as attr, the ID will be the input's name.
    *                             Example: class=my-class
    * @param array  $user_options (Optional):
    *                             plugin        : slimselect | select2 | bootstrap-select    Default: 'slimselect'
    *                             lang          : MUST correspond to one subfolder of [PLUGINS_DIR]countries/country-list/country/cldr/
    *                             *** for example 'en', or 'fr_FR'              Default: 'en'
    *                             flags         : true or false.              Default: true
    *                             *** displays flags into option list
    *                             flag_size     : 16 or 32                    Default: 32
    *                             return_value  : 'name' or 'code'            Default: 'name'
    *                             *** type of the value that will be returned
    *                             show_tick     : true or false
    *                             *** shows a checkmark beside selected options Default: true
    *                             live_search   : true or false               Default: true
    */

Live examples with code are available here:
javascript-plugins.php#slimselect-example javascript-plugins.php#bootstrap-select-example
javascript-plugins.php#select2-example

Time Select list

The addTimeSelect() function generates an hours:minutes drop-down list. The options allow you to set a minimum time, a maximum time, the interval in minutes between each option, and the separator character.

$form->addTimeSelect($select_name [, $label = '', $attr = '', $user_options = array()]);
    /**
     * adds an hours:minutes select dropdown
     * @param  string $select_name
     * @param  string $label       (Optional) The select label
     * @param  string (Optional)   Can be any HTML input attribute or js event.
     *                             attributes must be listed separated with commas.
     *                             If you don't specify any ID as attr, the ID will be the name of the select.
     *                             Example : class=my-class
     * @param array  $user_options (Optional) :
     *                             min       : the minimum time in hour:minutes                   Default: '00:00'
     *                             max       : the maximum time in hour:minutes                   Default: '23:59'
     *                             step      : the step interval in minutes between each option   Default: 1
     *                             format    : '12hours' or '24hours'                             Default : '24hours'
     *                             display_separator : the displayed separator character between hours and minutes  Default : 'h'
     *                             value_separator   : the value separator character between hours and minutes  Default : ':'
     * @return $this
     */

Live examples with code are available here:
https://www.phpformbuilder.pro/templates/bootstrap-5-forms/booking-form.php https://www.phpformbuilder.pro/templates/bootstrap-5-forms/car-rental-form.php

Radio Btns

  1. Add your radio buttons
  2. Call printRadioGroup
$form->addRadio($group_name, $label, $value [, $attr = '']);
    /**
    * Adds radio button to $group_name element
    *
    * @param string $group_name The radio button groupname
    * @param string $label The radio button label
    * @param string $value The radio button value
    * @param string $attr  (Optional) Can be any HTML input attribute or js event.
    *                      attributes must be listed separated with commas.
    *                      Example: checked=checked
    */

Print Radio Group

$form->printRadioGroup($group_name, $label [, $inline = true, $attr = '']);
    /**
    * Prints radio buttons group.
    *
    * @param string $group_name The radio button group name
    * @param string $label (Optional) The radio buttons group label
    * @param string $inline (Optional) True or false.
    *                                  Default is true.
    * @param string $attr (Optional) Can be any HTML input attribute or js event.
    *                       attributes must be listed separated with commas.
    *                       If you don't specify any ID as attr, the ID will be the input's name.
    *                       Example: class=my-class
    */

Example

    $form->addRadio('myRadioBtnGroup', 'choice one', 'value 1');
    $form->addRadio('myRadioBtnGroup', 'choice two', 'value 2', 'checked=checked');
    $form->addRadio('myRadioBtnGroup', 'choice three', 'value 3');
    $form->printRadioGroup('myRadioBtnGroup', 'Choose one please', true, 'required=required');

Several plugins are available to replace the ugly browser default radio buttons with nice ones:

Checkboxes

  1. Add your checkboxes
  2. Call printCheckboxGroup
$form->addCheckbox($group_name, $label, $value [, $attr = '']);
    /**
    * Adds checkbox to $group_name
    *
    * @param string $group_name The checkbox groupname (will be converted to an array of indexed value)
    * @param string $label The checkbox label
    * @param string $value The checkbox value
    * @param string $attr  (Optional) Can be any HTML input attribute or js event.
    *                      attributes must be listed separated with commas.
    *                      Example: checked=checked
    */

Print Checkbox Group

$form->printCheckboxGroup($group_name, $label [, $inline = true, $attr = '']);
    /**
    * Prints checkbox group.
    *
    * @param string $var (Optional) description
    *
    * @param string $group_name The checkbox button group name
    * @param string $label (Optional) The checkbox group label
    * @param string $inline (Optional) True or false.
    *                                  Default is true.
    * @param string $attr (Optional) Can be any HTML input attribute or js event.
    *                       attributes must be listed separated with commas.
    *                       If you don't specify any ID as attr, the ID will be the input's name.
    *                       Example: class=my-class
    */

Example

    $form->addCheckbox('myCheckboxGroup', 'choice one', 'value 1');
    $form->addCheckbox('myCheckboxGroup', 'choice two', 'value 2', 'checked=checked');
    $form->addCheckbox('myCheckboxGroup', 'choice three', 'value 3', 'checked=checked');
    $form->printCheckboxGroup('myCheckboxGroup', 'Check please: ', true, 'required=required');

Several plugins are available to replace the ugly browser default checkboxes with nice ones:

Buttons

For a single button, just call addBtn() and let $btnGroupName empty.

For button group, call addBtn() for each button, give a name to $btnGroupName, then call printBtnGroup()

$form->addBtn($type, $name, $value, $text [, $attr = '', $btnGroupName = '']);
    /**
    * Adds a button to the form
    *
    * If $btnGroupName is empty, the button will be automatically displayed.
    * Otherwise, you'll have to call printBtnGroup to display your btnGroup.
    *
    * @param string $type The html button type
    * @param string $name The button name
    * @param string $value The button value
    * @param string $text The button text
    * @param string $attr (Optional) Can be any HTML input attribute or js event.
    *                                 attributes must be listed separated with commas.
    *                                 If you don't specify any ID as attr, the ID will be the input's name.
    *                                 Example: class=my-class,onclick=alert(\'clicked\');
    * @param string $btnGroupName (Optional) If you want to group several buttons, group them then call printBtnGroup.
    *
    */

Print Btn Group

$form->printBtnGroup($btnGroupName);
    /**
    * Prints buttons group.
    *
    * @param string $btnGroupName The buttons' group name
    * @param string $label (Optional) The buttons group label
    *
    */

Single button example

$form->addBtn('submit', 'myBtnName', 1, 'Submit form', 'class=btn btn-primary');

Button group example

    $form->addBtn('submit', 'mySubmitBtnName', 1, 'Submit form', 'class=btn btn-primary', 'myBtnGroup');
    $form->addBtn('button', 'myCancelBtnName', 0, 'Cancel', 'class=btn btn-danger, onclick=alert(\'cancelled\');', 'myBtnGroup');
    $form->printBtnGroup('myBtnGroup');

Custom HTML

You can add some HTML code at any place you want when creating your form.

This way, you can:

$form->addHtml($html [, $element_name = '', $pos = 'after']);
    /**
    * Adds HTML code at any place of the form
    *
    * @param string $html The html code to add.
    * @param string $element_name (Optional) If not empty, the html code will be inserted.
    *                                        just before or after the element.
    * @param string $pos (Optional) If $element_name is not empty, defines the position
    *                               of the inserted html code.
    *                               Values can be 'before' or 'after'.
    */

When your HTML is linked to an element, always call addHtml() BEFORE creating the element.

To add helper texts, icons, buttons, or any input group addon, use the shortcut functions:

Add HTML between elements

    $form->addInput('text', 'input-name', '', 'Your name: ');
    $form->addHtml('<p class="alert alert-danger">Your email address is required</p>');
    $form->addInput('text', 'email', '', 'Your email', 'required');

Your email address is required

Prepend or append HTML to elements

    $form->addInput('text', 'input-name-2', '', 'Your name: ');
    $form->addHtml('<p class="form-text alert alert-danger">Your email address is required</p>', 'email-2', 'after');
    $form->addInput('text', 'email-2', '', 'Your email', 'required');

Your email address is required

Custom HTML with input wrapper

wrapper can be one or two html elements

$form->addInputWrapper($html, $element_name);
    /**
    * Wraps the element with HTML code.
    *
    * @param string $html The HTML code to wrap the element with.
    *                     The HTML tag must be opened and closed.
    *                     Example: <div class="my-class"></div>
    * @param string $element_name The form element to wrap.
    */

Example

    $form->addInputWrapper('<div class="bg-dark rounded p-2"><div class="bg-white rounded p-2"></div></div>', 'imput-wrapped');
    $form->addInput('text', 'imput-wrapped', '', 'Input wrapped with custom divs');

Rendering

Render

Renders the form.

Set $debug to true if you wants to display HTML code

Set $display to false if you wants to return HTML code but not display on page

$form->render([$debug = false, $display = true]);
    /**
    * Renders the HTML code of the form.
    *
    * @param boolean $debug   (Optional) True or false.
    *                         If true, the HTML code will be displayed
    * @param boolean $display (Optional) True or false.
    *                         If false, the HTML code will be returned but not displayed.
    *
    */

Ajax loading

PHP Form Builder allows you to load your forms with Ajax.

Loading in Ajax allows to:

  • integrate your forms on any HTML page
  • load the forms asynchronously, which is suitable for your page loading speed

To load your form with Ajax:

  1. 1 Create your form using the built-in PHP functions and save it in a PHP file somewhere on your server.
    Set the ajax option to true to enable Ajax loading.
    Here's a sample code:
    <?php
    
    use phpformbuilder\Form;
    use phpformbuilder\Validator\Validator;
    
    /* =============================================
        start session and include form class
    ============================================= */
    
    $form_id = 'my-form';
    
    session_start();
    include_once rtrim($_SERVER['DOCUMENT_ROOT'], DIRECTORY_SEPARATOR) . '/phpformbuilder/Form.php';
    
    /* =============================================
        validation if posted
    ============================================= */
    
    if ($_SERVER["REQUEST_METHOD"] == "POST" && Form::testToken($form_id) === true) {
        // do stuff
    }
    
    /* ==================================================
        The Form
    ================================================== */
    
    $form = new Form($form_id, 'horizontal', 'data-fv-no-icon=true, novalidate');
    // $form->setMode('development');
    
    // enable Ajax loading
    $form->setOptions(['ajax' => true]);
    
    // add your fields & plugins here
    
    // render the form
    $form->render();
    
  2. 2 In your main file (html):
    Create a div with a specific id, for instance:
    <div id="ajax-form"></div>
  3. 3 In your main file (html):
    Add the JavaScript code to load your form:
    <!-- Ajax form loader -->
    
    <!-- Change the src url below if necessary -->
    <script src="/phpformbuilder/plugins/ajax-data-loader/ajax-data-loader.min.js"></script>
    
    <script>
        // --- SETUP YOUR FORM(S) BELOW IN THE "ajaxForms" VARIABLE ---
        var ajaxForms = [
            {
                formId: 'ajax-contact-form-1',
                container: '#ajax-form',
                url: 'ajax-forms/contact-form-1.php'
            }
        ];
    
        // --- NO NEED TO CHANGE ANYTHING AFTER THIS LINE ---
        // --- COPY/PASTE THE FOLLOWING CODE IN THE HTML FILE THAT WILL LOAD THE FORM ---
    
        document.addEventListener('DOMContentLoaded', function() {
            ajaxForms.forEach(function(currentForm) {
                const $formContainer = document.querySelector(currentForm.container);
                if (typeof($formContainer.dataset.ajaxForm) === 'undefined') {
                    fetch(currentForm.url)
                    .then((response) => {
                        return response.text()
                    })
                    .then((data) => {
                        $formContainer.innerHTML = '';
                        $formContainer.dataset.ajaxForm = currentForm;
                        $formContainer.dataset.ajaxFormId = currentForm.formId;
                        loadData(data, currentForm.container);
                    }).catch((error) => {
                        console.log(error);
                    });
                }
            });
        });
    </script>

You'll find an example here: https://www.phpformbuilder.pro/templates/bootstrap-5-forms/ajax-loaded-contact-form-1.html

useLoadJs

Use the great LoadJs library to load CSS & JavaScript plugins dependencies.

This feature is perfect for fast loading optimization ; it requires to include the LoadJs JavaScript library in your page

Details & sample codes here: javascript-plugins.php#async-loading-with-load-js-library

$form->useLoadJs($bundle = '');
    /**
    * load scripts with loadJS
    * https://github.com/muicss/loadjs
    * @param  string $bundle   optional loadjs bundle name to wait for
    * @return void
    */

Print plugins includes

The printIncludes() function inserts the CSS & JavaScript files required by each plugin used in your form.

Call printIncludes() at the right places (generally css inside your <head></head> section, and js just before </body>.

If your form contains no plugin, no need to call this function.

printIncludes($type, $debug = false, $display = true, $combine_and_compress = true);
    /**
    * Prints html code to include css or js dependancies required by plugins.
    * i.e.:
    *     <link rel="stylesheet" ... />
    *     <script src="..."></script>
    *
    * @param string  $type                 value : 'css' or 'js'
    * @param boolean $debug                (Optional) True or false.
    *                                      If true, the html code will be displayed
    * @param boolean $display              (Optional) True or false.
    *                                      If false, the html code will be returned but not displayed.
    * @param boolean $combine_and_compress (Optional) True or false.
    *                                      If true, dependancies are combined and compressed into plugins/min/ folder.
    * @return $this
    */

About optimization

PHP Form Builder is conceived for maximum optimization and speedy loading time.

Detailed explanations available here: Optimization (CSS & JS dependencies)

Example with colorpicker plugin

    $form->addInput('text', 'my-color', '', 'Pick a color:', 'data-colorpicker=true');

    // call this just before </head>
    $form->printIncludes('css');
<link href="../../phpformbuilder/plugins/colorpicker/themes/classic.min.css" rel="stylesheet" media="screen">

    $form->addInput('text', 'my-color', '', 'Pick a color:', 'data-colorpicker=true');

    // call this just before </body>
    $form->printIncludes('js');
<script src="../../phpformbuilder/plugins/colorpicker/pickr.min.js"></script>

Print plugins JS code

Prints the JS code generated by the plugin.

If your form contains no plugin, no need to call this function.

$form->printJsCode($debug = false);
    /**
    * Prints js code generated by plugins.
    * @param boolean $debug   (Optional) True or false.
    *                         If true, the HTML code will be displayed
    * @param boolean $display (Optional) True or false.
    *                         If false, the HTML code will be returned but not displayed.
    */

Example with colorpicker plugin

    $form->addInput('text', 'my-color', '', 'Pick a color:', 'data-colorpicker=true');
    $form->printJsCode();
    <script type="text/javascript">
        document.addEventListener('DOMContentLoaded', function(event) {
            phpfbColorpicker["#my-color"] = Pickr.create({
                // ...
            });
        });
    </script>

Utilities

Input Groups

Input Groups allow having several inputs/selects on the same line in horizontal forms.

You can group up to twelve elements.

There's two ways to set arguments:

  •     // 1st way: each fieldname as argument
        $form->groupElements('street', 'zip', 'countries');
  •     // 2nd way: a single array including all fieldnames as argument
        $fields = array('street', 'zip', 'countries');
        $form->groupElements($fields);

Always create your input group BEFORE creating the input elements.

$form->groupElements($input1, $input2 [, $input3 = '', $input4 = '', $input5 = '', $input6 = '', $input7 = '', $input8 = '', $input9 = '', $input10 = '', $input11 = '', $input12 = '']);
    /**
    * Allows to group inputs in the same wrapper
    *
    * Arguments can be:
    *     -    a single array with fieldnames to group
    *     OR
    *     -    fieldnames given as strings
    *
    * @param string|array $input1 The name of the first input of the group
    *                             OR
    *                             array including all fieldnames
    *
    * @param string $input2 The name of the second input of the group
    * @param string $input3 [optional] The name of the third input of the group
    * @param string $input4 [optional] The name of the fourth input of the group
    * @param string ...etc.
    */

Input Groups Example

    $form->startFieldset('Personal informations');
    $form->groupElements('street', 'zip', 'countries');
    $form->setCols(3, 4);
    $form->addInput('text', 'street', '', 'Your address: ', 'placeholder=street,required=required');
    $form->setCols(0, 2);
    $form->addInput('text', 'zip', '', '', 'placeholder=zip code,required=required');
    $form->setCols(0, 3);
    $form->addOption('countries', '', 'Countries');
    $form->addOption('countries', 'United States', 'United States');
    $form->addOption('countries', 'Canada', 'Canada');
    $form->addOption('countries', 'France', 'France');
    $form->addSelect('countries', '', '');
    $form->endFieldset();
Personal informations

Set Cols

The setCols() function wraps label and fields with columns.

The columns can only be set in horizontal forms.

$form->setCols($labelsCols, $fieldsCols [, $breakpoint = 'sm']);

Bootstrap 4 / 5 auto column
Bootstrap 4 & Bootstrap 5 allows automatic-width columns.
To build automatic-width columns, set $fieldsCols to -1

    /**
    * Shortcut for
    * $options = array(
    *        'horizontalLabelCol'       => 'col-' . $breakpoint . '-' . $labelsCols,
    *        'horizontalOffsetCol'      => 'col-' . $breakpoint . '-offset-' . $labelsCols,
    *        'horizontalElementCol'     => 'col-' . $breakpoint . '-' . $fieldsCols,
    * );
    * $form->setOptions($options);
    *
    * @param number $labelsCols number of columns for label
    * @param number $fieldsCols number of columns for fields
    * @param string $breakpoint Bootstrap's breakpoints: xs | sm | md |lg
    *
    */

Example

$form->setCols(3, 9);
$form->addInput('text', 'username', '', 'Name');
Will generate the following markup:
    <div class="form-group row justify-content-end">
        <label for="username" class="col-sm-3 col-form-label">
            Name
        </label>
        <div class="col-sm-9">
            <input id="username" name="username" type="text" value=""  class="form-control">
        </div>
    </div>
Equivalent to:
    $options = array(
        'horizontalLabelCol'       => 'col-sm-3',
        'horizontalElementCol'     => 'col-sm-9'
    );
    $form->setOptions($options);
    $form->addInput('text', 'username', '', 'Name');

Bootstrap 4 automatic-width example

    $form->setCols(-1, -1, 'sm');
    $form->groupElements('user-name', 'user-first-name');
    $form->addInput('text', 'user-name', '', 'Name', 'required, placeholder=Name');
    $form->addInput('text', 'user-first-name', '', 'First name', 'required, placeholder=First Name');

    $form->setCols(-1, -1); // without breakpoint
    $form->addIcon('user-email', '<i class="bi bi-envelope" aria-hidden="true"></i>', 'before');
    $form->addInput('email', 'user-email', '', '', 'required, placeholder=Email');
Will generate the following markup:
    <div class="form-group row justify-content-end">
        <label for="user-name" class="col-sm col-form-label">
            Name <sup class="text-danger">* </sup>
        </label>
        <div class="col-sm">
            <input id="user-name" name="user-name" type="text" value="" required placeholder="Name" class="form-control fv-group">
        </div>
        <label for="user-first-name" class="col-sm col-form-label">
            First name <sup class="text-danger">* </sup>
        </label>
        <div class="col-sm">
            <input id="user-first-name" name="user-first-name" type="text" value="" required placeholder="First Name" class="form-control fv-group">
        </div>
    </div>
    <div class="form-group row justify-content-end">
        <div class=" col-sm">
            <div class="input-group">
                <div class="input-group-prepend">
                    <span class="input-group-text"><i class="bi bi-envelope" aria-hidden="true"></i></span>
        </div>
        <input id="user-email" name="user-email" type="email" value="" required placeholder="Email" class="form-control">
    </div>

Add Helper

Adds helper text after the chosen field

$form->addHelper($helper_text, $element_name);

addHelper() MUST always be called BEFORE creating the element

    /**
    * Shortcut to add element helper text
    *
    * @param string $helper_text    The helper text or HTML to add.
    * @param string $element_name   the helper text will be inserted just after the element.
    */

Example

    $form->addHelper('Enter your last name', 'last-name');
    $form->addInput('text', 'last-name', '', 'Last name', 'required');
Enter your last name

Add Addon

Adds button or text addon before or after the chosen field

$form->addAddon($input_name, $addon_html, $pos);
    /**
    * shortcut to prepend or append button or text addon to an input
    * @param string $input_name the name of target input
    * @param string $addon_html  button or text addon html code
    * @param string $pos        before | after
    */

Example

    $addon = '<button class="btn btn-warning" type="button" onclick="document.getElementById(\'input-with-button-after\').value=\'\';">reset</button>';
    $form->addAddon('input-with-button-after', $addon, 'after');
    $form->addInput('text', 'input-with-button-after', '', 'Your name');

Add Heading

Add a HTML heading tag.

$form->addHeading($heading_html, $heading_tag = 'h4', $attr = '')
    /**
     * add an HTML heading
     *
     * @param  string $html         the heading content text or HTML
     * @param  string $tag_name     (Optional) the heading tag name (h1, h2, ...)
     * @param  string $attr         (Optional) the heading attributes
     * @return void
     */

Example

    $form->addHeading('Please fill the form', 'h5', 'class=text-muted');

Please fill the form

Add Icon

Adds an icon before or after the chosen field

$form->addIcon($input_name, $icon_html, $pos);
    /**
    * shortcut to prepend or append icon to an input
    * @param string $input_name the name of target input
    * @param string $icon_html  icon html code
    * @param string $pos        before | after
    */

Example

    $form->addIcon('username', '<i class="bi bi-person-fill" aria-hidden="true"></i>', 'before');
    $form->addInput('text', 'username', '', 'Name');

buildAlert (static method)

Build an alert div according to the given framework

Form::buildAlert($content_text, $framework, $type = 'success');
    /**
     * build an Alert message according to the framework HTML
     *
     * @param  string $content_text
     * @param  string $framework     bs4|bs5|bulma|foundation|material|tailwind|uikit
     * @param  string $type  success|primary|info|warning|danger
     * @return string the alert HTML code
     */

Example

    Form::buildAlert('<strong>This is a danger alert example</strong>', 'bs5', 'danger');

startRow

Start a new HTML row according to the form framework

$form->startRow($additionalClass = '', $id = '')
    /**
     * Start a HTML row
     *
     * @param string $additionalClass
     * @param string $id
     * @return $this
     */

Example

    $form->startRow();
<div class="row">

Others examples in templates:

Special Offer Sign Up Form
Order Form

endRow

End a row HTML div

$form->endRow()

startCol

Start a new HTML responsive column according to the form framework

$form->startCol($col_number, $breakpoint = 'sm', $additionalClass = '', $id = '')
    /**
     * Start a column HTML div
     *
     * @param number $col_number - the number of columns between 1 and 12
     * @param string $breakpoint - xs, sm, md or lg
     * @param string $additionalClass
     * @param string $id
     * @return $this
     */

Example

    $form->startCol(6);
<div class="col-sm-6">

Others examples in templates:

Special Offer Sign Up Form
Order Form

endCol

End a column HTML div

$form->endCol()

Center Content

Center any field or element horizontally on the page. The centered elements can be displayed on the same line or stacked.

$form->centerContent($center = true, $stack = false);
    /**
    * @param  boolean $center
    * @param  boolean $stack
    */

Example

    $form->centerContent();
    $form->addBtn('submit', 'submit-btn', 1, 'Submit', 'class=btn btn-success');

Email Sending

sendMail() function

$sent_message = Form::send($options, $smtp_settings = array());

See details at Email Sending

Registering / Clearing values

Global registration process

PHP Form Builder manages the memorization of fields and posted values without you needing taking any action.

If your form is posted with errors, i.e., validation fails, the posted values are automatically displayed in the corresponding fields.

To set the default value of a field, it must be saved in the PHP session in this way:

$_SESSION['form-id']['field-name'] = 'my-value';

If the form is posted, the field will have the posted value. Otherwise, it will have the default value registered in the PHP session.

Here's the global workflow:

  1. You create your form and add fields.
    PHP Form Builder registers each field name in PHP session: $_SESSION['form-id']['fields'][] = 'field-name';
  2. You post the form
  3. You validate the posted values: $validator = Form::validate('form-id');
  4. If the validation fails:
    The error messages are stored in PHP session: $_SESSION['errors'][$form_ID] as $field => $message
  5. You instanciate your form again:
    PHP Form Builder registers the posted values in PHP session: $_SESSION['form-id']['field-name'] = $_POST['my-value'];
    PHP Form Builder gets and displays the session value and the possible error for each field.

registerValues (static function)

When you instantiate a form, it automatically stores corresponding posted values in session unless you called the clear function before creating your form.

Values are registered this way: $_SESSION['form-id']['field-name']

You can call Form::registerValues('form-id') manually at any time.

Form::registerValues('form-id');
    /**
    * register all posted values in session
    * @param string $form_ID
    *
    * ex: $_SESSION['form-id']['field-name'] = $_POST['field-name'];
    */

mergeValues (static function)

mergeValues is used to merge previously registered values in a single array.
Usefull for step forms to send all steps values by email or store into database for example.

Form::mergeValues(array('step-form-1', 'step-form-2', 'step-form-3'));
    /**
    * merge previously registered session vars => values of each registered form
    * @param  array $forms_array array of forms IDs to merge
    * @return array pairs of names => values
    *                           ex: $values[$field_name] = $value
    */

clear (static function)

Clears the corresponding previously registered values from session.

Form::clear('form-id');

Validation

Overview

PHP Form Builder comes with two different validation systems.

  1. PHP Validation
    The form is validated after being posted. It is a PHP validation, essential for security.
  2. JavaScript Validation
    The fields are validated on the fly for better User Experience.

Never forget: The only way to avoid security issues is PHP Validation.
Users can easily disable JavaScript and get around the JavaScript validation.

PHP Validation

Basics

To create a new validator object and auto-validate required fields, use this standard-code
(replace 'form-id' with your form ID)

    /* =============================================
    validation if posted
    ============================================= */

    if ($_SERVER["REQUEST_METHOD"] == "POST" && Form::testToken('form-id') === true) {

        // create validator & auto-validate required fields
        $validator = Form::validate('form-id');

        // additional validation
        $validator->maxLength(100)->validate('message');
        $validator->email()->validate('user-email');

        // check for errors
        if ($validator->hasErrors()) {
        $_SESSION['errors']['form-id'] = $validator->getAllErrors();
        } else {
            // validation passed, you can send email or do anything
        }
    }
$validator = Form::validate('form-id');
This loads the Validator, then creates a new Validator object, and finally validates the required fields, if any.
Required fields validation is automatic. There's nothing more to do.
    // additional validation
    $validator->maxLength(100)->validate('message');
    $validator->email()->validate('user-email');
Then we use $validator native methods for others validations
(email, date, length, ...)
    // check for errors
    if ($validator->hasErrors()) {
        $_SESSION['errors']['form-id'] = $validator->getAllErrors();
    }
If there are some errors, we register them in the PHP session.
The form will automatically display the error messages.

Dependent fields validation

Dependent fields validation is something magic.

Form::validate() validates the required dependent fields only if their parent field value matches the condition to display them.

If you use additional validators, for example $validator->email()->validate('user-email'); you have to test if the field has to be validated or not according to your dependent fields conditions:

    if ($_POST['parent-field'] == 'value') {
        $validator->email()->validate('user-email');
    }

Php Validator Methods

To validate an array, use the dot syntax.

Example: <select name="my-field[]" multiple="multiple">

    $validator->required()->validate('my-field.0');

    /* if at least 2 values must be selected: */

    $validator->required()->validate(array('my-field.0', 'my-field.1'));

The validation is done with blackbelt's php-validation class.

Complete documentation at https://github.com/blackbelt/php-validation.

I just added these features:

  • Captcha validation support for the included captcha plugin
  • Multilanguage support
  • Patterns validation for the included passfield plugin:
    • $validator->hasLowercase()->validate($field_name);
    • $validator->hasUppercase()->validate($field_name);
    • $validator->hasNumber()->validate($field_name);
    • $validator->hasSymbol()->validate($field_name);
    • $validator->hasPattern('/custom_regex/')->validate($field_name);

Available methods:

Requiredcaptcha($field, $message = null)
Added to validate included captcha plugin.
Requiredrecaptcha($secret_key, $message = null)
Added to validate included recaptcha plugin.
Requiredrequired($message = null)
The field value is required.
Optionalemail($message = null)
The field value must be a valid email address string.
Optionalfloat($message = null)
The field value must be a float.
Optionalinteger($message = null)
The field value must be an integer.
Optionaldigits($message = null)
The field value must be a digit (integer with no upper bounds).
Requiredmin($limit, $include = TRUE, $message = null)
The field value must be greater than $limit (numeric). $include defines if the value can be equal to the limit.
Optionalmax($limit, $include = TRUE, $message = null)
The field value must be less than $limit (numeric). $include defines if the value can be equal to the limit.
Requiredbetween($min, $max, $include = TRUE, $message = null)
The field value must be between $min and $max (numeric). $include defines if the value can be equal to $min and $max.
RequiredminLength($length, $message = null)
The field value must be greater than or equal to $length characters.
OptionalmaxLength($length, $message = null)
The field value must be less than or equal to $length characters.
Requiredlength($length, $message = null)
The field must be $length characters long.
Requiredmatches($field, $label, $message = null)
One field matches another one (i.e. password matching)
OptionalnotMatches($field, $label, $message = null)
The field value must not match the value of $field.
RequiredstartsWith($sub, $message = null)
The field must start with $sub as a string.
OptionalnotStartsWith($sub, $message = null)
The field must not start with $sub as a string.
RequiredendsWith($sub, $message = null)
THe field must end with $sub as a string.
OptionalnotEndsWith($sub, $message = null)
The field must not end with $sub as a string.
Optionalip($message = null)
The field value is a valid IP, determined using filter_var.
Optionalurl($message = null)
The field value is a valid URL, determined using filter_var.
Optionaldate($message = null)
The field value is a valid date, can be of any format accepted by DateTime()
RequiredminDate($date, $format, $message = null)
The date must be greater than $date. $format must be of a format on the page http://php.net/manual/en/datetime.createfromformat.php
RequiredmaxDate($date, $format, $message = null)
The date must be less than $date. $format must be of a format on the page http://php.net/manual/en/datetime.createfromformat.php
Optionalccnum($message = null)
The field value must be a valid credit card number.
RequiredoneOf($allowed, $message = null)
The field value must be one of the $allowed values. $allowed can be either an array or a comma-separated list of values. If comma-separated, do not include spaces unless intended for matching.
RequiredhasLowercase($message = '')
The field value must contain at least one lowercase character.
RequiredhasUppercase($message = '')
The field value must contain at least one uppercase character.
RequiredhasNumber($message = '')
The field value must contain at least one numeric character.
RequiredhasSymbol($message = '')
The field value must contain at least one symbol character.
RequiredhasPattern($pattern, $message = '')
The field value must match regex.
Optionalcallback($callback, $message = '', $params = array())
Define your own custom callback validation function. $callback must pass an is_callable() check. $params can be any value, or an array if multiple parameters must be passed.
Required
: Empty fields are NOT VALID
Optional
: Empty fields are VALID

Validation examples

Validation examples code

Main validation code

    if ($_SERVER["REQUEST_METHOD"] == "POST" && Form::testToken('my-form-id') === true) {

        // create validator & auto-validate required fields
        $validator = Form::validate('contact-form-1');

        // additional validation
        $validator->email()->validate('email-field-name');

        // add custom message if you want:
        $validator->integer('You must enter a number')->validate('number-field-name');

        $validator->captcha('captcha')->validate('captcha-field-name');

        // check for errors
        if ($validator->hasErrors()) {
            $_SESSION['errors']['my-form-id'] = $validator->getAllErrors();
        }
    }

Checkboxes validation

If we want at least one checked:

    $form->addCheckbox('chk_group', 'check 1', 1);
    $form->addCheckbox('chk_group', 'check 2', 2);
    $form->addCheckbox('chk_group', 'check 3', 3);
    $form->printCheckboxGroup('chk_group', 'check one: ');

    /* Validation: */

    if(!isset($_POST['chk_group']) || !is_array($_POST['chk_group'])) {

        /* if none are posted, we register the error */

        $validator->required('check at least one checkbox please')->validate('chk_group');
    }

Trigger an error manually

If we want at least 2 checked:

    $form->addCheckbox('chk_group', 'check 1', 1);
    $form->addCheckbox('chk_group', 'check 2', 2);
    $form->addCheckbox('chk_group', 'check 3', 3);
    $form->printCheckboxGroup('chk_group', 'check at least 2: ');

    /* Validation: */

    if(!isset($_POST['chk_group']) || !is_array($_POST['chk_group']) || count($_POST['chk_group']) < 2) {

        /* if less than two are posted, we create a tricky validation which always throws an error */

        $validator->maxLength(-1, 'Check at least two please')->validate('chk_group');
    }

Radio validation

    $form->addRadio('rating', 'Good', 'Good');
    $form->addRadio('rating', 'Fair', 'Fair');
    $form->addRadio('rating', 'Poor', 'Poor');
    $form->printRadioGroup('rating', 'Rate please: ', false, 'required=required');

    /* Validation: */

    $validator->required('Please rate')->validate('rating');
    

Multiple select validation

    $form->addOption('product-choice[]', 'Books', 'Books');
    $form->addOption('product-choice[]', 'Music', 'Music');
    $form->addOption('product-choice[]', 'Photos', 'Photos');
    $form->addSelect('product-choice[]', 'What products are you interested in ?
(multiple choices)', 'required=required, multiple=multiple, style=min-height:130px'); /* Validation: */ $validator->required('Please choose one or several product(s)')->validate('product-choice.0');

Recaptcha validation

    $form->addRecaptcha('YOUR_RECAPTCHA_KEY_HERE');

    /* Validation: */

    $validator->recaptcha('YOUR_RECAPTCHA_SECRET_KEY_HERE', 'Recaptcha Error')->validate('g-recaptcha-response');

Conditional validation

    if ($_SERVER["REQUEST_METHOD"] == "POST" && Form::testToken('my-form-id') === true) {

        // 'field_name' will be validated only if $_POST['parent_field_name'] === 'Yes'
        $_SESSION['my-form-id']['required_fields_conditions']['field_name'] = array(
            'parent_field'  => 'parent_field_name',
            'show_values'   => 'Yes',
            'inverse'       => false
        );

        // create validator & auto-validate required fields
        $validator = Form::validate('my-form-id');

        // check for errors
        if ($validator->hasErrors()) {
            $_SESSION['errors']['my-form-id'] = $validator->getAllErrors();
        }
    }

Validation multilanguage support

The default language is 'en' (English).

The currently available languages are:

  • de
  • en
  • es
  • fr
  • pt_br

If you need other language support:

  1. Add your language to form/Validator/Validator.php => _getDefaultMessage($rule, $args = null)
  2. instantiate with your language as second argument:
    $validator = Form::validate('contact-form-1', 'fr');

If you add your language, please share it so it can benefit other users.

Real-time Validation (Javascript)

Getting started

Real-time Validation is done with the formvalidation plugin.

  1. Call plugin like you would do with any other plugin:
    $form->addPlugin('formvalidation', '#my-form'); // replace "my-form" with your form name
  2. Fields with the following HTML5 types/attributes will be automatically validated:
        min="..."
        max="..."
        maxlength="..."
        minlength="..."
        pattern="..."
        required
        type="color"
        type="email"
        type="range"
        type="url"
  3. To add any custom validation, use HTML5 attributes with validatorname and validator option:
    <?php
        $form->addInput('text', 'username', 'Username', '', 'data-fv-not-empty, data-fv-not-empty___message=The username is required and cannot be empty');

    Complete list of HTML5 validation attributes available at example using html 5 inputs and attributes

Validator icons

The JavaScript validation plugin is configured to show feedback valid/invalid icons on the right of each field.

You can disable them this way:

$form = new Form('booking-form', 'horizontal', 'data-fv-no-icon=true, novalidate');

DEBUG mode

In some complex cases, you may want to see which fields are validated or not:

  1. Enable the DEBUG mode:
    $form = new Form('booking-form', 'horizontal', 'data-fv-debug=true, novalidate');
  2. Open your browser's console, fill in some fields, then post your form.
  3. The form will not be submitted:
    In DEBUG mode, submit is disabled.
    The browser's console will display the validation results:
jquery validator debug console

JavaScript validation - Available methods

The complete list of validators methods is available here: https://formvalidation.io/guide/validators/.

Form Submission

When the user submits the form, the validator automatically sends the form if all the fields are valid.
If you want to disable this behavior add the data-fv-no-auto-submit attribute to your form:

$form = new Form('my-form', 'vertical', 'data-fv-no-auto-submit=true, novalidate');

Callback & JavaScript validation API

The callback function allows you to enable/disable validators and use the Form Validation plugin API the way you want.

Create a function named fvCallback - The validator plugin will call it when it's ready.
Then you can use all the validator's API.

  • The callback function name is fvCallback
  • You can access the form validator instance this way:
    var form = forms['my-form'];
    
    // form.fv is the validator
    form.fv.on('core.form.invalid', function() {
        // do stuff
    });

example of use:

<script type="text/javascript">
var fvCallback = function() {
    var form = forms['my-form'];

    // form.fv is the validator
    // you can then use the formvalidation plugin API
    form.fv.on('core.form.invalid', function() {
        // do stuff
    });
};
</script>

Examples

All the templates use the JavaScript validation plugin.

Multilanguage support

JavaScript Validation languages files are in phpformbuilder/plugins/formvalidation/dist/js/language/

To set your language:

  1. Find your language file in phpformbuilder/plugins/formvalidation/dist/js/locales/
  2. Add the validation plugin this way:
    $js_replacements = array('%language%' => 'fr_FR');
    $form->addPlugin('formvalidation', '#form-name', 'default', $js_replacements);
    where fr_FR is the name of your language file.

More

The Formvalidation plugin comes with rich & complex features.

The complete documentation is available on the Formvalidation plugin's official site.

Email Sending

sendMail function (static)

$sent_message = Form::sendMail($options, $smtp_settings = array());
    /**
    * Send an email with posted values and custom content
    *
    * Tests and secures values to prevent attacks (phpmailer/extras/htmlfilter.php => HTMLFilter)
    * Uses custom html/css template and replaces shortcodes - syntax : {fieldname} - in both html/css templates with posted|custom values
    * Creates an automatic html table with vars/values - shortcode : {table}
    * Merges html/css to inline style with Pelago Emogrifier
    * Sends email and catches errors with Phpmailer
    * @param  array  $options
    *                     sender_email                    : the email of the sender
    *                     sender_name [optional]          : the name of the sender
    *                     reply_to_email [optional]       : the email for reply
    *                     recipient_email                 : the email destination(s), separated with commas
    *                     cc [optional]                   : the email(s) of copies to send, separated with commas
    *                     bcc [optional]                  : the email(s) of blind copies to send, separated with commas
    *                     subject                         : The email subject
    *                     isHTML                          : Send the mail in HTML format or Plain text (default: true)
    *                     textBody                        : The email body if isHTML is set to false
    *                     attachments [optional]          : file(s) to attach : separated with commas, or array (see details inside function)
    *                     template [optional]             : name of the html/css template to use in phpformbuilder/mailer/email-templates/
                                                 (default: default.html)
    *                     human_readable_labels [optional]: replace '-' ans '_' in labels with spaces if true (default: true)
    *                     values                          : $_POST
    *                     filter_values [optional]        : posted values you don't want to include in the email automatic html table
    *                     custom_replacements [optional]  : array to replace shortcodes in email template. ex : array('mytext' => 'Hello !') will replace {mytext} with Hello !
    *                     sent_message [optional]         : message to display when email is sent. If sent_message is a string it'll be automatically wrapped into an alert div. Else if sent_message is html code it'll be displayed as is.
    *                     debug [optional]                : displays sending errors (default: false)
    *                     smtp [optional]                 : use smtp (default: false)
    *
    * @param  array  $smtp_settings
    *                         host :       String      Specify main and backup SMTP servers - i.e: smtp1.example.com, smtp2.example.com
    *                         smtp_auth:   Boolean     Enable SMTP authentication
    *                         username:    String      SMTP username
    *                         password:    String      SMTP password
    *                         smtp_secure: String      Enable TLS encryption. Accepted values: tls|ssl
    *                         port:        Number      TCP port to connect to (usually 25 or 587)
    *
    * @return string sent_message
    *                         success or error message to display on the page
    */

The fields named *-token and *submit-btn are automatically filtered.
It means that the posted values will not appear in the email sent.

Minimal Example

The following code will :

  • Load default email template phpformbuilder/mailer/email-templates/default[.html/.css]
  • Replace template shortcode {table} with an automatic HTML table with vars/ posted values
  • Merge HTML/CSS to inline style with Pelago Emogrifier
  • Send email and catch errors with PHPMailer
    $options = array(
        'sender_email'     =>  'contact@phpformbuilder.pro',
        'recipient_email'  =>  'john.doe@gmail.com',
        'subject'          =>  'contact from PHP Form Builder'
    );
    $sent_message = Form::sendMail($options);

Your message has been successfully sent !

Example with SMTP

    $smtp_settings = array(
        'host'        => 'smtp1.example.com',
        'smtp_auth'   => true,
        'username'    => 'myname',
        'password'    => 'mypassword',
        'smtp_secure' => 'tls',
        'port'        => 25
    );

    $options = array(
        'sender_email'     =>  'contact@phpformbuilder.pro',
        'recipient_email'  =>  'john.doe@gmail.com',
        'subject'          =>  'contact from PHP Form Builder',
        'smtp'             =>  true
    );
    $sent_message = Form::sendMail($options, $smtp_settings);

Your message has been successfully sent !

Example with custom template

    // Create 'my-custom-template.html' and 'my-custom-template.css' in the 'phpformbuilder/mailer/email-templates-custom/' folder
    // You can use shortcodes in your HTML template, they will be automatically replaced with the posted values.
    // For instance, {user-email} will be replaced with the real $_POST['user-email'] value.

    // You can use the special {table} shortcode to display a complete table with all the posted fieldnames / values.

    // Then:

    $email_config = array(
        'sender_email'    => 'contact@phpformbuilder.pro',
        'sender_name'     => 'PHP Form Builder',
        'recipient_email' => addslashes($_POST['user-email']),
        'subject'         => 'Contact From PHP Form Builder',
        'template'        => 'my-custom-template.html',
        'filter_values'   => 'submit-btn, token',
        'debug'           => true
    );
    $sent_message = Form::sendMail($email_config);

Your message has been successfully sent !

Example with Text Email (no template, no HTML)

    $email_config = array(
        'sender_email'    => 'contact@phpformbuilder.pro',
        'sender_name'     => 'PHP Form Builder',
        'recipient_email' => addslashes($_POST['user-email']),
        'subject'         => 'Contact From PHP Form Builder',
        'textBody'        => $_POST['message'], // textBody is required or the message won't be sent.
        'isHTML'          => false,
        'debug'           => true
    );
    $sent_message = Form::sendMail($email_config);

Your message has been successfully sent !

Complete Example using a styled template

The following code will :

  • Load a styled email template phpformbuilder/mailer/email-templates/custom[.html/.css]
  • Replace template shortcodes, including header image and colors, with the values set in $replacements
  • Replace the other template's shortcodes with the posted values
  • Merge HTML/CSS to inline style with Pelago Emogrifier
  • Send email and catch errors with Phpmailer
    // email HTML template placeholders replacements
    $replacements = array(
        'tpl-header-image'              => 'https://www.phpformbuilder.pro/assets/images/phpformbuilder-preview-600-160.png',
        'tpl-content-dark-background'   => '#363331',
        'tpl-content-light-background'  => '#FAF6F2',
        'user-full-name'                => $_POST['user-first-name'] . ' ' . $_POST['user-name']
    );

    $email_config = array(
        'sender_email'        => 'contact@phpformbuilder.pro',
        'sender_name'         => 'Php Form Builder',
        'recipient_email'     => addslashes($_POST['user-email']),
        'subject'             => 'Contact From Php Form Builder',
        'filter_values'       => 'email-templates',
        'template'            => 'custom.html',
        'custom_replacements' => $replacements,
        'debug'               => true
    );
    $sent_message = Form::sendMail($email_config);

Your message has been successfully sent !

To create custom email templates:

  1. Copy/paste an existing HTML/CSS template from phpformbuilder/mailer/email-templates/ and save it into phpformbuilder/mailer/email-templates-custom/ (or create a new HTML file + a new css file with both same name)
  2. Use the shortcode {table} in your HTML template if you want to add an automatic HTML table with all posted values.
  3. Write the fieldnames between braces in your template.
    They'll be replaced automatically with posted values.
    For example: Hello {user-first-name} {user-name}
  4. [optional] You can use the custom_replacements option to replace specific texts in email with specific values
  5. Call sendMail() function and set your HTML template in template option

How to replace array values using sendMail() function

The best way to replace the posted array values in a custom email template is to create non-array indexed values, then add them in the sendMail custom_replacements option.

Example using array values

<?php
    /*
    Example with three posted colors
    Email template will use {color_1}, {color_2}, {color_3}
    */

    // create index
    $i = 1;

    // loop through posted values
    foreach ($_POST['color'] as $color) {

        // name indexed variable and give it posted value
        $var = 'color_' . $i;
        $$var = $color;

        // increment index
        $i++;
    }

    $options = array(
        // [...]
        'custom_replacements'  => array(
            'color_1' => $color_1,
            'color_2' => $color_2,
            'color_3' => $color_3
        ),
        // [...]
    );

    $sent_message = Form::sendMail($options);

Your message has been successfully sent !

Attachments Examples

Examples using the FileUpload plugin

The path of the uploaded files is defined in the fileuploader plugin configuration (variable $fileUpload_config) when you instantiate the fileuploader plugin.

To get the information about the uploaded file you have to call the function FileUploader::getPostedFiles

Single file:

    // at the beginning of your file
    use fileuploader\server\FileUploader;
    include_once rtrim($_SERVER['DOCUMENT_ROOT'], DIRECTORY_SEPARATOR) . 'phpformbuilder/plugins/fileuploader/server/class.fileuploader.php';

    // once the form is validated
    $options = array(
        [...]
    );

    if (isset($_POST['user-file']) && !empty($_POST['user-file'])) {
        // set the filepath according to the path defined in the fileuploader plugin configuration
        $path = rtrim($_SERVER['DOCUMENT_ROOT'], DIRECTORY_SEPARATOR) . '/file-uploads/';

        // get the posted filename
        $posted_file = FileUploader::getPostedFiles($_POST['user-file']);
        $filename    = $posted_file[0]['file'];

        // add the attachment to the email
        $options['attachments'] = $path . $filename;
    }

    $msg = Form::sendMail($options);

Multiple files separated with commas:

    // at the beginning of your file
    use fileuploader\server\FileUploader;
    include_once rtrim($_SERVER['DOCUMENT_ROOT'], DIRECTORY_SEPARATOR) . 'phpformbuilder/plugins/fileuploader/server/class.fileuploader.php';

    // once the form is validated
    $options = array(
        [...]
    );

    if (isset($_POST['user-files']) && !empty($_POST['user-files'])) {
        // set the filepath according to the path defined in the fileuploader plugin configuration
        $path = rtrim($_SERVER['DOCUMENT_ROOT'], DIRECTORY_SEPARATOR) . '/file-uploads/';

        // get the posted filename
        $posted_files = FileUploader::getPostedFiles($_POST['user-files']);
        $attachments = array();
        foreach ($posted_files as $pf) {
            $filename = $pf['file'];
            $attachments[] = $path . $filename;
        }

        // add the attachments to the email
        $options['attachments'] = implode(',', $attachments);
    }

    $msg = Form::sendMail($options);

Examples using input type="file"

Single file:

    $form->addInput('file', 'myFile', '', 'file: ');

    $attachments = array(
        array(
            'file_path' => $_FILES['myFile']['tmp_name'],
            'file_name' => $_FILES['myFile']['name']
        )
    );

    $options = array(
        [...]
        'attachments' => $attachments,
        [...]
    );

    $msg = Form::sendMail($options);

Multiple files:

    $form->addInput('file', 'myFile', '', 'file: ');
    $form->addInput('file', 'mySecondFile', '', 'file: ');

    $attachments = array(
        array(
            'file_path' => $_FILES['myFile']['tmp_name'],
            'file_name' => $_FILES['myFile']['name']
        ),
        array(
            'file_path' => $_FILES['mySecondFile']['tmp_name'],
            'file_name' => $_FILES['mySecondFile']['name']
        )
    );

    $options = array(
        [...]
        'attachments' => $attachments,
        [...]
    );
    $msg = Form::sendMail($options);

Database PDO Class

This PDO wrapper class is based on Jeff L. Williams's Ultimate MySQL PDO Database Class.

The main class is phpformbuilder/database/DB.php.

The PDO complete documentation is available here: https://www.phpformbuilder.pro/documentation/db-help.php.

Database connection

  1. Set your localhost/production database connection settings in phpformbuilder/database/db-connect.php
  2. Add the use statement at the beginning of your PHP code.
  3. Add the require statements to load your connection settings and the DB class.
  4. Connect & write your queries

Example:

use phpformbuilder\database\DB;

                // register the database connection settings
require_once 'phpformbuilder/database/db-connect.php';

// Include the database class
require_once 'phpformbuilder/database/DB.php';

// Then connect to the database
$db = new DB();

// or connect and show errors
$db = new DB(true);

// or connect and register errors in a variable
if ($db = new DB() !== true) {
    $error_message = $db->error();
}

Database Select Examples

$db->query - With SQL code and placeholders

// Execute a SQL query with (or without) placeholders, then fetch the results
$sql = 'SELECT * FROM test_table';
$db->query($sql);

// Execute the same query in debug mode
$rows = $db->query($sql, $values, true);

// Execute a SQL query with placeholders
$sql = 'SELECT id, name, age FROM test_table WHERE active = :active';
$values = array('active' => true);
$db->query($sql, $values);

// loop through the results
while ($row = $db->fetch()) {
    echo $row->name . '<br>';
}

// or fetch all the records then loop
// (this function should not be used if a huge number of rows have been selected, otherwise it will consume a lot of memory)
$rows = $db->fetchAll();

foreach($rows as $row) {
    echo $row->name . '
'; }

$db->select - The DB class creates the SQL query for you

// Setup the query
$columns = array('id', 'name');
$where   = false;
$order   = 'name';
$db->select('test_table', $columns, $where, $order);

// loop through the results
while ($row = $db->fetch()) {
    echo $row->name . '<br>';
}

// or fetch all the records then loop
// (this function should not be used if a huge number of rows have been selected, otherwise it will consume a lot of memory)
$rows = $db->fetchAll();

foreach($rows as $row) {
    echo $row->name . '
'; }

$db->convertQueryToSimpleArray - Convert the rows to an associative array then loop

$db->select('states', 'state_code, state_name');
$result = $db->fetchAll(PDO::FETCH_ASSOC);

$array = $db->convertQueryToSimpleArray($result, 'state_name', 'state_code');
print_r($array);

/* will output something like:
Array
(
    [AL] => Alabama
    [AK] => Alaska
    [AZ] => Arizona
)
*/

Database Insert

// Insert a new record
$values = array('name' => 'Riley', 'age' => 30, 'active' => false);

if (!$db->insert('test_table', $values)) {
    $msg = Form::buildAlert($db->error(), 'bs5', 'danger');
} else {
    $id  = $db->getLastInsertId();
    $msg = Form::buildAlert('1 Record inserted ; id = #' . $id, 'bs5', 'success');
}

echo $msg;

// Try it in debug mode
$success = $db->insert('test_table', $values, true);

Database Update

// Update an existing record
$update = array('age' => 35);
$where  = array('name' => 'Riley');

if (!$db->update('test_table', $update, $where)) {
    $msg = Form::buildAlert($db->error(), 'bs5', 'danger');
} else {
    $msg = Form::buildAlert('Database updated successfully', 'bs5', 'success');
}

echo $msg;

Database Delete

// Delete records
$where = array('active' => false);

if (!$db->delete('test_table', $where)) {
    $msg = Form::buildAlert($db->error(), 'bs5', 'danger');
} else {
    $msg = Form::buildAlert('1 record deleted', 'bs5', 'success');
}

echo $msg;

Errors & Debug

All functions that perform queries can be called with debug mode enabled.

The queries are simulated, and the results are displayed (including any errors).

Alternatively, you can display the potential errors in specific cases, for example, if a query fails.

All the errors are memorized by the errorEvent() function. Then you can call $db->error() to retrieve them (see the examples above).

Security

Protection against XSS
(Cross-Site Scripting)

How it works

  1. Each fieldname is registered in the PHP session when a form is created.
  2. Each posted value is registered in the PHP session when a form is posted.
  3. If validation is ok, call Form::clear('form-name'); to clear all previously registered values
  4. If validation fails, the form will fill fields using the user-posted values stored in the PHP session, protected using htmlspecialchars().

To display posted values on your pages, always protect with htmlspecialchars(): htmlspecialchars($_POST['value'])

To register posted values into your database:

  • protect with addslashes(): addslashes(htmlspecialchars($_POST['value']))
  • or just with addslashes id you want to keep html intact: addslashes($_POST['value'])
  • or use built-in Mysql class protection

Protection against CSRF
(Cross-Site Request Forgeries)

A security token is automatically added to each form.

The token is valid for 1800 seconds (30mn) without refreshing the page.

Validate posted token this way:

    if(Form::testToken('my-form-id') === true) {
        // token valid, no CSRF.
    }

Extending main class

Extending PHP Form Builder allows creating a complete form or form parts using a single customized function.

Created form or parts can be validated the same way, using a single customized function.

Very useful if you want, for example:

  • Create a complete contact form and use it on several projects
  • Create several similar fields in a single form
  • Create and reuse several fields in different forms

See live examples with code in Templates

See phpformbuilder/FormExtended.php code

Chaining methods

All the public non-static methods can be chained.

The classic way:

/* ==================================================
    The Form
    ================================================== */

    $form = new Form('contact-form-2', 'vertical', 'novalidate');
    $form->startFieldset('Please fill in this form to contact us');
    $form->addInput('text', 'user-name', '', 'Your name: ', 'required');
    $form->addInput('email', 'user-email', '', 'Your email: ', 'required');
    $form->addHelper('Enter a valid US phone number', 'user-phone');
    $form->addInput('text', 'user-phone', '', 'Your phone: ', 'required, data-fv-phone, data-fv-phone-country=US');
    $form->addTextarea('message', '', 'Your message: ', 'cols=30, rows=4, required');
    $form->addPlugin('word-character-count', '#message', 'default', array('%maxAuthorized%' => 100));
    $form->addCheckbox('newsletter', 'Suscribe to Newsletter', 1, 'checked=checked');
    $form->printCheckboxGroup('newsletter', '');
    $form->addRecaptcha('recaptcha-code-here');
    $form->addBtn('submit', 'submit-btn', 1, 'Submit', 'class=btn btn-success');
    $form->endFieldset();
    $form->addPlugin('icheck', 'input', 'default', array('%theme%' => 'square-custom', '%color%' => 'green'));

    // JavaScript validation
    $form->addPlugin('formvalidation', '#contact-form-2');

Using chained methods:

$form = new Form('contact-form-2', 'vertical', 'novalidate');
$form->startFieldset('Please fill in this form to contact us')->addInput('text', 'user-name', '', 'Your name: ', 'required')
    ->addInput('email', 'user-email', '', 'Your email: ', 'required')
    ->addHelper('Enter a valid US phone number', 'user-phone')
    ->addInput('text', 'user-phone', '', 'Your phone: ', 'required, data-fv-phone, data-fv-phone-country=US')
    ->addTextarea('message', '', 'Your message: ', 'cols=30, rows=4, required')
    ->addPlugin('word-character-count', '#message', 'default', array('%maxAuthorized%' => 100))
    ->addCheckbox('newsletter', 'Suscribe to Newsletter', 1, 'checked=checked')
    ->printCheckboxGroup('newsletter', '')
    ->addRecaptcha('recaptcha-code-here')
    ->addBtn('submit', 'submit-btn', 1, 'Submit', 'class=btn btn-success')
    ->endFieldset()
    ->addPlugin('icheck', 'input', 'default', array('%theme%' => 'square-custom', '%color%' => 'green'))

    // JavaScript validation
    ->addPlugin('formvalidation', '#contact-form-2');

Sources & Credits

https://www.phpformbuilder.pro/#credits