PHP library to create and validate html forms

Overview

FormManager

Build Status Scrutinizer Code Quality

Note: this is the documentation of FormManager 6.x

For v5.x version Click here

Installation:

This package requires PHP>=7.1 and is available on Packagist:

composer require form-manager/form-manager

Create a field

FormManager is namespaced, but you only need to import a single class into your context:

use FormManager\Factory as F;

Use the imported factory to create all form elements:

'name-field']); //Add or remove attributes $name->setAttribute('title', 'This is the name input'); $name->removeAttribute('class'); $name->setAttributes([ 'required', 'readonly', 'tabindex' => 2, 'maxlength' => 50 ]); //Set the value $name->setValue('MyName'); //Use magic properties to get/set/remove attributes $name->class = 'name-field'; $name->required = false; unset($name->readonly); ">
//Create an input type="text" element
$name = F::text();

//Create the input with a label
$name = F::text('Please, introduce your name');

//Or with extra attributes
$name = F::text('Please, introduce your name', ['class' => 'name-field']);

//Add or remove attributes
$name->setAttribute('title', 'This is the name input');
$name->removeAttribute('class');
$name->setAttributes([
    'required',
    'readonly',
    'tabindex' => 2,
    'maxlength' => 50
]);

//Set the value
$name->setValue('MyName');

//Use magic properties to get/set/remove attributes
$name->class = 'name-field';
$name->required = false;
unset($name->readonly);

List of all available inputs:

All HTML5 field types are supported:

  • F::checkbox($label, $attributes)
  • F::color($label, $attributes)
  • F::date($label, $attributes)
  • F::datetimeLocal($label, $attributes)
  • F::email($label, $attributes)
  • F::file($label, $attributes)
  • F::hidden($value, $attributes)
  • F::month($label, $attributes)
  • F::number($label, $attributes)
  • F::password($label, $attributes)
  • F::radio($label, $attributes)
  • F::range($label, $attributes)
  • F::search($label, $attributes)
  • F::select($label, $options, $attributes)
  • F::submit($label, $attributes)
  • F::tel($label, $attributes)
  • F::text($label, $attributes)
  • F::textarea($label, $attributes)
  • F::time($label, $attributes)
  • F::url($label, $attributes)
  • F::week($label, $attributes)

Note that all inputs accepts the same arguments except hidden and select.

Validation

This library uses internally symfony/validation to perform basic html5 validations and error reporting. HTML5 validation attributes like required, maxlength, minlength, pattern, etc are supported, in addition to intrinsic validations assigned to each input like email, url, date, etc.

$email = F::email();

$email->setValue('invalid-email');

//Validate the value
if ($email->isValid()) {
    return true;
}

//Get errors
$error = $email->getError();

//Print the first error message
echo $error;

//Iterate through all messages
foreach ($error as $err) {
    echo $err->getMessage();
}

//You can also customize/translate the error messages
$email->setErrorMessages([
    'email' => 'The email is not valid',
    'required' => 'The email is required',
    'maxlength' => 'The email is too long, it must have {{ limit }} characters or less',
]);

//And add more symfony validators
$ip = F::text();
$ip->addConstraint(new Constraints\Ip());

See all constraints supported by symfony

Render html

$name = F::text('What is your name?', ['name' => 'name']);

echo $name;
What is your name? ">
<label for="id-input-1">What is your name?label> <input id="id-input-1" type="text" name="name">

Set a custom template using {{ label }} and {{ input }} placeholders:

{{ input }}
'); echo $name; ">
$name->setTemplate('{{ label }} 
{{ input }}
'
); echo $name;
What is your name?
">
<label for="id-input-1">What is your name?label> <div class="input-content"><input id="id-input-1" type="text" name="name">div>

If you want to wrap the previous template in a custom html, use the {{ template }} placeholder:

$name->setTemplate('
{{ template }}
'
); echo $name;
What is your name?
">
<fieldset><label for="id-input-1">What is your name?label> <div class="input-content"><input id="id-input-1" type="text" name="name">div>fieldset>

Grouping fields

Group the fields to follow a specific data structure:

Group

Groups allow to place a set of inputs under an specific name:

$group = F::group([
    'name' => F::text('Username'),
    'email' => F::email('Email'),
    'password' => F::password('Password'),
]);

$group->setValue([
    'name' => 'oscar',
    'email' => '[email protected]',
    'password' => 'supersecret',
]);

Radio group

Special case for radios where all inputs share the same name with different values:

$radios = F::radioGroup([
    'red' => 'Red',
    'blue' => 'Blue',
    'green' => 'Green',
]);

$radios->setValue('blue');

Submit group

Special case to group several submit buttons under the same name but different values:

$buttons = F::submitGroup([
    'save' => 'Save the row',
    'duplicate' => 'Save as new row',
]);

$buttons->setName('action');

Group collection

Is a collection of values using the same group:

$groupCollection = F::groupCollection(
    f::group([
        'name' => F::text('Name'),
        'genre' => F::radioGroup([
            'm' => 'Male',
            'f' => 'Female',
            'o' => 'Other',
        ]),
    ])
]);

$groupCollection->setValue([
    [
        'name' => 'Oscar',
        'genre' => 'm'
    ],[
        'name' => 'Laura',
        'genre' => 'f'
    ],
])

Multiple group collection

Is a collection of values using various groups, using the field type to identify which group is used by each row:

$multipleGroupCollection = F::multipleGroupCollection(
    'text' => f::group([
        'type' => F::hidden(),
        'title' => F::text('Title'),
        'text' => F::textarea('Body'),
    ]),
    'image' => f::group([
        'type' => F::hidden(),
        'file' => F::file('Image file'),
        'alt' => F::text('Alt text'),
        'text' => F::textarea('Caption'),
    ]),
    'link' => f::group([
        'type' => F::hidden(),
        'text' => F::text('Link text'),
        'href' => F::url('Url'),
        'target' => F::select([
            '_blank' => 'New window',
            '_self' => 'The same window',
        ]),
    ]),
]);

$multipleGroupCollection->setValue([
    [
        'type' => 'text',
        'title' => 'Welcome to my page',
        'text' => 'I hope you like it',
    ],[
        'type' => 'image',
        'file' => 'avatar.jpg',
        'alt' => 'Image of mine',
        'text' => 'This is my photo',
    ],[
        'type' => 'link',
        'text' => 'Go to my webpage',
        'href' => 'https://oscarotero.com',
        'target' => '_self',
    ],
]);

Datalist

Datalist are also allowed, just use the createDatalist() method:

$input = F::search();

$datalist = $input->createDatalist([
    'female' => 'Female',
    'male' => 'Male'
]);

echo $input;
echo $datalist;

Forms

We need a form to put all this things together.

{$input}
"; } echo $loginForm->getClosingTag(); ">
$loginForm = F::form([
    'username' => F::text('User name'),
    'password' => F::password('Password'),
    '' => F::submit('Login'),
]);

$loginForm->setAttributes([
    'action' => 'login.php',
    'method' => 'post',
]);

//Load data from globals $_GET, $_POST, $_FILES
$loginForm->loadFromGlobals();

//Load data passing the arrays
$loginForm->loadFromArrays($_GET, $_POST, $_FILES);

//Or load from PSR-7 server request
$loginForm->loadFromServerRequest($serverRequest);

//Get loaded data
$data = $loginForm->getValue();

//Print the form
echo $loginForm;

//Access to specific inputs:
echo $loginForm->getOpeningTag();
echo '

Login:

'
; echo $loginForm['username']; echo '
'
; echo $loginForm['password']; echo '
'
; echo $loginForm['']; echo $loginForm->getClosingTag(); //Iterate with all inputs echo $loginForm->getOpeningTag(); echo '

Login:

'
; foreach ($loginForm as $input) { echo "
{$input}
"
; } echo $loginForm->getClosingTag();
Comments
  • 6.1.0  version break compatibility with Select optgroups handling

    6.1.0 version break compatibility with Select optgroups handling

    In version 6.0.1 if you have in form:

    		F::select(
    			'TestSelect',
    			 [
    				'Group1' => ['1' => 'one', '2' => 'two' ],
    				'Group2' => ['1' => 'one', '2' => 'two' ],
    				'Group3' => ['1' => 'one', '2' => 'two' ]
    			]
    			,[ 'id' => 'county', 'multiple' => 'multiple', 'class' => 'select2' ]
    		),
    

    you will got select with optgroups like: image

    But in version 6.1 there was no any erros, but select will look like (got only groups): image

    If such breaking chenge made intentionally there should be check and exception with hint how developer must adjust their code. But really it is is bug on my mind. There was no any deprecation in Select interface, so breaking change should not be happened in stable versions (e.g. 6.*).

    opened by Hubbitus 7
  • fix array normalizing

    fix array normalizing

    in case when Select::val($value) $value is not integer or string, eg bool : Select::applyValues(array $value) will not apply old normalize method, array_flip() will raise warning

    opened by andrdru 7
  • Examples System

    Examples System

    I've added the basis for being able to easily show example of using FormManager alongside their PHP and HTML output.

    To add an example simple create a file in the examples/example directory with a short example at the top, and the form code below.

    To really see the examples it's best to be able to run the code, I've hosted a copy of the examples here:

    http://pata.cat/tools/form-manager/examples/index.php

    which should be online for the foreseeable future. but anybody is welcome to host a new copy (or perhaps setup a git-pages).

    Feel free to suggest better ways to achieve any of these examples.

    opened by Patabugen 6
  • Field::duplicate error

    Field::duplicate error

    If I try to add a duplicate field (as per the example in the docs):

    'friends' => Field::duplicate([
        'name' => Field::text()->label('Name'),
        'email' => Field::email()->label('email'),
        'age' => Field::number()->label('Age')
    ])->addDuplicate(),
    

    I get this error:

    PHP 3. FormManager\\Fields\\Duplicable->add() /var/www/html/fmtest2/index.php:37
    PHP 4. FormManager\\Fields\\Collection->add() /var/www/html/fmtest2/vendor/form-manager/form-manager/src/Fields/Duplicable.php:27
    PHP Fatal error: Call to a member function addDuplicate() on a non-object in /var/www/html/fmtest2/index.php on line 41
    
    opened by m1 6
  • Add Group without prefixing the name

    Add Group without prefixing the name

    Hey,

    I'd like to be able to add FormGroups but have the FormManager not put fields in those groups into arrays.

    For example:

    <?php
                $fieldContainer = \FormManager\Builder::group();
                $fieldContainer->add($arrayOfFields);
                $form->add( [ $someKey => $fieldContainer ] );
    

    I'm trying to use groups for visual separating decoration and I'm adding a $fieldContainer->render() function to do that.

    Perhaps a fix would be to not group the field names if the keys are numeric, and not defined?

    opened by Patabugen 5
  • How to get

    How to get "name" attribute

    Before version 4.3, I could get the name attribute using $input->attr('name') because name is a tag attribute, but now returns null.

    There are a new method to get the input name?

    opened by eusonlito 4
  • Message error

    Message error

    Hi,

    How can I redefine an error message?

    FormManager\Inputs\Email::$error_message = "foo";
    

    I'm not sure that's correct...

    And, other question, can you add a CSRF token?

    opened by TonyLight 4
  • The attribute

    The attribute "name" is read only!

    How can I create a new Input and assign him a name without add function?

    Using README example I can't:

    //Create an input type="text" element
    $name = F::text();
    
    //Use the jQuery syntax to set/get/remove attributes:
    $name->attr('name', 'username');
    
    InvalidArgumentException in InputTrait.php line 107:
    The attribute "name" is read only!
    

    Thanks.

    opened by eusonlito 3
  • How I can clear previous

    How I can clear previous "select" options

    I need to clear the current options with new options (differents). How can I do it?

    There are some empty method like jQuery?

    My example:

    $form['states_id']->options([1 => 'aaaa']);
    
    ... very long process ...
    
    $form['states_id']->options([2 => 'bbbb']);
    

    After last step, $form['status_id'] has first and second assignment, but I need to clear first options without define again or other field redefinitions. Something like:

    $form['states_id']->options([1 => 'aaaa']);
    
    ... very long process ...
    
    $form['states_id']->empty()->options([2 => 'bbbb']);
    

    Thanks :)

    opened by eusonlito 3
  • Default values are lost after load call

    Default values are lost after load call

    I have this definition:

    $form = new FormManager\Containers\Form;
    
    $form->add([
        'action' => F::hidden()->val('edit'),
        'id' => F::hidden()
    ]);
    

    Then, I load a default value to id:

    $form->load(['id' => 1]);
    

    After that, I lost action value:

    var_dump($form['action']);
    
    Hidden {#183 â–Ľ
      +input: Input {#184 â–Ľ
        #name: "input"
        #parent: Form {#180 â–¶}
        #close: null
        #attributes: array:2 [â–Ľ
          "type" => "hidden"
          "value" => ""
        ]
        #data: []
        #vars: []
        #html: null
        #sanitizer: null
        #validators: []
        #error: null
        #key: "action"
      }
      #labelPosition: 0
      #render: null
      #rendering: false
    }
    
    opened by eusonlito 3
  • Select input value issue

    Select input value issue

    Thanks for the great library.

    I came across an issue where I had the following options in my select

    '' => ' -- Any --',
    '0' => 'Studio',
    '1' => '1 Bedroom',
    '2' => '2 Bedrooms',
    

    Unfortunately because php treats '' == 0 as true, both of the top two options are treated as selected.

    I've updated the comparison to $val === $value to fix this issue.

    opened by davidrushton 3
  • FR: Please add {{id}} placeholder in template

    FR: Please add {{id}} placeholder in template

    Said I have form:

    	$filterRealtyTypeTemplate = '<li>{{ input }}{{ label }}</li>';
    
    	$form = F::form([
    		'filter_realty_type' => F::radioGroup(
    			[
    				'residential'	=> F::radio('Residential real estate')->setTemplate($filterRealtyTypeTemplate)
    				,'rural'	=> F::radio('Rural properties')->setTemplate($filterRealtyTypeTemplate)
    				,'commercial'	=> F::radio('Commercial real estate')->setTemplate($filterRealtyTypeTemplate)
    			]
    		)
            )
    

    And I would like access values residential, rural and so on in my template like:

    $filterRealtyTypeTemplate = '<li><a href="#tab_realty_type_{{ id }}">{{ input }}{{ label }}</a></li>';
    

    In my case for use with jQuery tabs plugin, but I think it would be helpfull in other cases too.

    Change seams trivial like do in Input.php:

        public function __toString()
        {
            if ($this->label) {
                return strtr($this->template, [
                    '{{ label }}' => (string) $this->label,
                    '{{ input }}' => parent::__toString(),
                    '{{ id }}' => $this->getAttribute('value') // !!!
                ]);
            }
    
            return parent::__toString();
        }
    

    If you wish I could prepare PR.

    P.S. Is it possible to provide the template for all radio objects once at radioGroup level?

    opened by Hubbitus 3
  • Fix PHPStan Level 5 problems

    Fix PHPStan Level 5 problems

    @oscarotero This is all I could do.

    The last one on Level 5 may be a Symfony problem

     ------ ----------------------------------------------------------------------------------------------------------
      Line   ValidationError.php
     ------ ----------------------------------------------------------------------------------------------------------
      43     Call to an undefined method Symfony\Component\Validator\ConstraintViolationListInterface::getIterator().
     ------ ----------------------------------------------------------------------------------------------------------
    

    Powered by @phpstan

    opened by szepeviktor 1
  • Use Symfony File constraints

    Use Symfony File constraints

    Hi,

    I tried to add a maxSize constraint from Symfony on a file input. Turns out it's not working because Symfony expect a Symfony\Component\HttpFoundation\File\File object.

    Is there any way to make file constraints work? If not, that would probably deserves a mention in the docs.

    opened by nlemoine 2
Releases(v6.1.2)
Owner
Oscar Otero
Web designer and developer 🦄
Oscar Otero
html-sanitizer is a library aiming at handling, cleaning and sanitizing HTML sent by external users

html-sanitizer html-sanitizer is a library aiming at handling, cleaning and sanitizing HTML sent by external users (who you cannot trust), allowing yo

Titouan Galopin 381 Dec 12, 2022
This shell script and PHP file create a browseable HTML site from the Zig standard library source.

Browseable Zig standard library This shell script and PHP file create a browseable HTML site from the Zig standard library source. The idea is to inve

Dave Gauer 3 Mar 20, 2022
A PHP library to read and validate EU Digital COVID Certificates

CovPassCheck PHP A PHP library to read and validate EU Digital COVID Certificates. Install composer require stwon/covpasscheck-php Usage Currently, th

Studentenwerk OstNiedersachsen 6 Feb 7, 2022
A library of powerful code snippets to help you get the job done with Gravity Forms and Gravity Perks.

Gravity Wiz Snippet Library Gravity Wiz is creating the most comprehensive library of snippets for Gravity Forms ever. We'll be consistently moving ou

Gravity Wiz 151 Dec 27, 2022
Fresns core library: Cross-platform general-purpose multiple content forms social network service software

About Fresns Fresns is a free and open source social network service software, a general-purpose community product designed for cross-platform, and su

Fresns 82 Dec 31, 2022
Learning about - Basic HTML & CSS, JSON, XML, Session & Cookies, CRUD Operations in Php using MySQL and Create MVC from scratch

This Project is based on course CSC 3215. Learning about - Basic HTML & CSS, JSON, XML, Session & Cookies, CRUD Operations in Php using MySQL and Create MVC (Model–View–Controller) from scratch. Just learning about web technologies, Not focusing on UI (Bootstrap or other 3rd-Party UI libraries or frameworks).

Alvi Hasan 5 Sep 21, 2022
Sanitize untrustworthy HTML user input (Symfony integration for https://github.com/tgalopin/html-sanitizer)

html-sanitizer is a library aiming at handling, cleaning and sanitizing HTML sent by external users (who you cannot trust), allowing you to store it and display it safely. It has sensible defaults to provide a great developer experience while still being entierely configurable.

Titouan Galopin 86 Oct 5, 2022
JSON schema models and generated code to validate and handle various data in PocketMine-MP

DataModels JSON schema models and generated code to validate and handle various data in PocketMine-MP This library uses php-json-schema-model-generato

PMMP 2 Nov 9, 2022
A set of classes to create and manipulate HTML objects abstractions

HTMLObject HTMLObject is a set of classes to create and manipulate HTML objects abstractions. Static calls to the classes echo Element::p('text')->cla

Emma Fabre 128 Dec 22, 2022
A challenge to develop frontend-backend forms and account creating.

Symfony + Vue (Back/Front) Helped and assisted by Vanessa and Paulo. This project have two sides, the back-end(Symfony) and the front-end(Vue.js) for

Rickelme Dias 1 Feb 10, 2022
PHP functions that help you validate structure of complex nested PHP arrays.

PHP functions that help you validate structure of complex nested PHP arrays.

cd rubin 7 May 22, 2022
The simplest way to create a dynamic sitemap for your self-coded website which you have made by using PHP/HTML/CSS/Js etc... Scripts.

Sitemap_index.xml The simplest way to create a dynamic sitemap for your self-coded website which you have made by using PHP/HTML/CSS/Js etc... Scripts

Tanish Raj 1 Oct 16, 2021
This module aims to validate if the pilot made his flights online on the IVAO and VATSIM networks

SMPirepValidator This module aims to validate if the pilot made his flights online on the IVAO and VATSIM networks SMPirepValidator v.1.0 for phpVMS (

SmartModules for phpVMS 1 Dec 13, 2021
Symfony Bundle to create HTML tables with bootstrap-table for Doctrine Entities.

HelloBootstrapTableBundle This Bundle provides simple bootstrap-table configuration for your Doctrine Entities. Used bootstrap-table version 1.18.3. I

Sebastian B 7 Nov 3, 2022
Formcreator is a plugin which allow creation of custom forms of easy access

Formcreator is a plugin which allow creation of custom forms of easy access. At the same time, the plugin allow the creation of one or more tickets when the form is filled.

GLPI plugins 135 Dec 22, 2022
đź”’ Built a recaptcha for Nifty that works with Wordpress's Gravity Forms

Recaptcha Fully Functioning spam filter that has 10 levels of security, but is slim and rpackaged to integrate with any Gravity Forms form WORKING EXA

Lisa Broadhead 1 May 17, 2022
Javascript-powered auto-completion functionality for your Symfony forms!

Symfony UX Autocomplete Javascript-powered auto-completion functionality for your Symfony forms! EXPERIMENTAL This component is currently experimental

Symfony 12 Dec 15, 2022
Ranting field for the Filament forms

Ranting field for the Filament forms

null 14 Dec 11, 2022
Greyhole uses Samba to create a storage pool of all your available hard drives, and allows you to create redundant copies of the files you store.

Greyhole Greyhole is an application that uses Samba to create a storage pool of all your available hard drives (whatever their size, however they're c

Guillaume Boudreau 245 Dec 18, 2022