Download the PHP package b2pweb/bdf-form without Composer
On this page you can find all versions of the php package b2pweb/bdf-form. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Informations about the package bdf-form
BDF Form
Library for handle form, and request validation.
Table of content
- Installation using composer
- Basic usage
- Handle entities
- Transformation process
- Embedded and array
- Field path and dependencies
- Choices
- Buttons
- Elements
- StringElement
- Url
- IntegerElement
- FloatElement
- BooleanElement
- DateTimeElement
- PhoneElement
- CsrfElement
- AnyElement
- StringElement
- Create a custom element
- Using custom form
- Using LeafElement
- Usage
- Custom child builder
- Error Handling
- Simple usage
- Printer
Installation using composer
Basic usage
To create a form, simply extends the class CustomForm
and implements method CustomForm::configure()
:
To display the form, call the ElementInterface::view()
method on the form object, and use the view object :
Now, you can submit data to the form, and perform validation :
Handle entities
The form system can be use to import, create or fill an entity using accessors :
- For
FormInterface::import()
the entity, useChildInterface::getter()
on the corresponding field. This method will useGetter
as extractor. - For fill an entity, using
FormInterface::attach()
followed byFormInterface::value()
, useChildInterface::setter()
. This method will useSetter
as hydrator. - For create a new instance of the entity, using
FormInterface::value()
, withoutattach()
, useFormBuilderInterface::generates()
. This method will useValueGenerator
.
Declaration :
Usage :
Transformation process
Here a description, step by step, of the transformation process, from HTTP value to model value. This process is reversible to generate HTTP value from model.
Note: This example is for leaf element contained into a form. For an embedded for or array, simply replace the leaf element process by the form process.
1 - Submit to buttons (scope: RootForm)
The first step perform by the RootForm
is to check the submit buttons.
If the HTTP data contains the button name, and the value match with the configured one, the button is marked as clicked.
Note: in reverse process, the clicked button value will be added to HTTP value
See :
ButtonInterface::submit()
ButtonInterface::clicked()
RootFormInterface::submitButton()
2 - Call transformers of the form (scope: Form)
Transformers of the container form are called. There are used to normalize input HTTP data to usable array value.
Note: the transformers are called in reverse order (i.e. last registered is first executed) when transform from HTTP to PHP and called in order for PHP to HTTP transformation
See:
TransformerInterface
FormBuilderInterface::transformer()
3 - Extract the HTTP field value (scope: Child)
At this step, the normalized HTTP value is passed to the child, and the current field value is extracted. If the value is not available, null is returned.
There is two extraction strategy :
- Array offset: This is the default strategy. Extract the field value using a simple array access like
$httpValue[$name]
. By default the HTTP field name is same as the child name. - Array prefix: This strategy can only be used for aggregate elements like for or array. Filter the HTTP value, and keep only fields which starts with the given prefix.
See:
HttpFieldsInterface::extract()
ChildBuilder::httpFields()
ChildBuilder::prefix()
ChildInterface::submit()
4 - Apply filters (scope: Child)
Once the field value is extracted, filters are applied. There are used for normalize and remove illegal values.
It's a destructive operation by definition (cannot be reversed), unlike transformers. There can be used for perform trim
or array_filter
.
Note: Unlike transformers, filters are only applied during transformation from HTTP to PHP. Do not use if it's a "view" operation, like decoding a string.
See:
FilterInterface
ChildBuilderInterface::filter()
5 - Set default value (scope: Child)
Set the default value is the filtered field value is considered as empty and a default value is provided.
A value is empty is it's an empty string ''
or array []
, or it's null
. 0
, 0.0
or false
are not considered as empty.
If not default value is given, the filtered value will be used.
Note: To set a default value, you should call
ChildBuilderInterface::default()
with PHP value
See:
HttpValue::orDefault()
ChildBuilderInterface::default()
6 - Call element transformers (scope: Element)
Works like Form transformers (step 2), but on the element value. If a transformer throws an exception, the submit process will be stopped, the raw HTTP value will be kept, and the element will be marked as invalid with the exception message as error.
The transformer exception behavior can be changed on the ElementBuilder
.
If the exception is ignored by calling ignoreTransformerException()
on the builder, the validation process will be performed on the raw HTTP value.
See:
ElementBuilderInterface::transformer()
ValidatorBuilderTrait::ignoreTransformerException()
ValidatorBuilderTrait::transformerErrorMessage()
ValidatorBuilderTrait::transformerErrorCode()
7 - Cast to PHP value (scope: Element)
The value is converted from HTTP value to usable PHP value, like a cast to int on IntegerElement
.
Note: this step is only performed on
LeafElement
implementations
See:
LeafElement::toPhp()
LeafElement::fromPhp()
8 - Validation (scope: Element)
Validate the PHP value of the element, using constraints.
See:
ElementInterface::error()
ElementInterface::valid()
ElementBuilderInterface::satisfy()
9 - Generate the form value (scope: Form)
Create the entity to fill by form values.
See:
ValueGeneratorInterface
FormInterface::value()
FormBuilderInterface::generator()
FormBuilderInterface::generates()
10 - Apply model transformer (scope: Child)
Call the model transformer, for transform input data to model data.
See:
ChildBuilderInterface::modelTransformer()
11 - Call accessor (scope: Child)
The accessor is used to fill the entity (in case of HTTP to PHP), or form import from entity (in case of PHP to form).
See:
ChildBuilder::setter()
ChildBuilder::getter()
ChildBuilder::hydrator()
ChildBuilder::extractor()
12 - Validate the form value (scope: Form)
Once the value is hydrated, it will be validated by the form constraints.
See:
FormInterface::valid()
FormInterface::error()
FormBuilderInterface::satisfy()
Embedded and array
Complex form structure can be created using embedded form and generic array element. Embedded form is useful for reuse a form into another.
This form will handle data like :
Or in HTTP format :
To improve readability and reusability, each embedded form can be declared in its own class :
You can also "flatten" the HTTP fields by using ChildBuilderInterface::prefix()
.
The embedded form will use a prefix instead of a sub-array.
Using prefix, the new data format is :
Or in HTTP format :
Field path and dependencies
In some cases, a field value should be validated or transformed using another field value.
It's for this goal that field dependencies are added : when a field depends on other, you can declare it using ChildBuilderInterface::depends()
.
Field path are used to access to the specific field.
Note: dependencies add complexity to the form, it's advisable to use a constraint on the parent form if possible.
To create a field path (and access to the desired field), you should use FieldPath::parse()
, or FieldFinderTrait
.
The format works like unix file system path, with /
as field separator, .
for the current field, and ..
for the parent.
Use /
at the start will define path as absolute.
Unlike unix path, by default, the path starts from the parent of the field (i.e. equivalent to ../
).
Format:
With :
.
to start the path from the current element (and not from it's parent). The current element must be an aggregate element like a form to works..
to start the path from the parent of the current element. This is the default behavior, so it's not necessary to start with "../" the path/
is the fields separator. When used at the beginning of the path it means that the path is absolute (i.e. start from the root element)fieldName
is a field name. The name is the declared one, not the HTTP field name
Usage:
The FieldPath
can also be used outside the form, and with embedded forms :
Choices
Choice system is use to allow only a set of values, like with HTML <selecte>
element.
To define a choice, simply call choice()
on the element builder, if supported.
A label can be defined using the key of associative array for the list of available values.
Once defined, the view system will automatically transform simple input elements to <select>
.
To render manually the choice, you can also call FieldViewInterface::choices()
to get choices array :
Buttons
Submit button can be defined to handle multiple action on the same form.
The form :
The view :
The controller :
Elements
StringElement
String element with Email constraint
Url
String element with Url constraint
IntegerElement
FloatElement
BooleanElement
Handle boolean value, like a checkbox.
The value will be considered as true if it's present, and is equals to the defined one (by default 1
).
Note: in HTTP a falsy value is an absent value, so a default value cannot be defined on a boolean element. To define a "view default" value, use
ElementBuilderInterface::value()
instead ofChildElementBuilder::default()
The default renderer will render a <input type="checkbox" />
with the defined http value and checked state.
DateTimeElement
PhoneElement
Handle phone number. The package giggsey/libphonenumber-for-php
is required to use this element.
This element will not return a string
but a PhoneNumber
instance.
CsrfElement
This element allows to mitigate CSRF. The package symfony/security-csrf
is required for this element.
Some element methods are disallowed, like import()
, any constraints, transformer or default.
The view will be rendered as <input type="hidden" />
.
AnyElement
An element for handle any value types. This is useful for create an inline custom element. But it's strongly discouraged : prefer use one of the native element, or create a custom one.
Create a custom element
You can declare custom elements to handle complex types, and reuse into any forms.
The examples bellow are for declare an element to handle UriInterface
objects, created using PSR-17 UriFactoryInterface
Using custom form
You can use a CustomForm
to declare an element.
The advantage of this method is that it don't need to implements low level interfaces, and require only to extends the CustomForm
class.
But it has the consequence of using more resources, has a lower flexibility, and cannot define a custom builder.
Using LeafElement
If declaring an element using the CustomForm
is not enough, or if you want to optimise this element, you can use the low level class LeafElement
to declare a custom element.
Usage
To use the custom element, simply call FormBuilderInterface::add()
with the element class name as second parameter :
Custom child builder
In some case, defining a custom child builder can be relevant, like for register model transformers.
To declare the child, simply extends ChildBuilder
class, and register to the Registry
:
Error Handling
When an error occurs on the form, a FormError
object is created with all errors.
Simple usage
If an error is on a child, use FormError::children()
to get the error.
If there is no error on children, but on the parent element, use FormError::global()
instead.
To get a simple string representation of errors, cast the errors to string.
To get an array representation in form [fieldName => error], use FormError::toArray()
.
Printer
To format errors with reusable way, a FormErrorPrinterInterface
can be implemented.
All versions of bdf-form with dependencies
symfony/property-access Version ~4.3|~5.0|~6.0|~7.0
symfony/validator Version ~4.3|~5.0|~6.0|~7.0
symfony/polyfill-php80 Version ~1.22