Skip to main content
Version: Thelia 2

Forms

Form definitions​

To create a new form create a new class that extend BaseForm then implement the method buildForm to describe your form.

<?php
namespace Thelia\Form;

use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Thelia\Core\Translation\Translator;
use Thelia\Model\AddressQuery;
use Thelia\Model\ModuleQuery;
use Thelia\Module\BaseModule;

class OrderDeliveryForm extends BaseForm
{
protected function buildForm(): void
{
$this->formBuilder
->add('delivery-address', IntegerType::class, [
'required' => true,
'constraints' => [
new Constraints\NotBlank(),
new Constraints\Callback(
[$this, 'verifyDeliveryAddress']
),
],
])
->add('delivery-module', IntegerType::class, [
'required' => true,
'constraints' => [
new Constraints\NotBlank(),
new Constraints\Callback(
[$this, 'verifyDeliveryModule']
),
],
]);
}

public function verifyDeliveryAddress($value, ExecutionContextInterface $context): void
{
$address = AddressQuery::create()
->findPk($value);

if (null === $address) {
$context->addViolation(Translator::getInstance()->trans('Address ID not found'));
}
}

public function verifyDeliveryModule($value, ExecutionContextInterface $context): void
{
$module = ModuleQuery::create()
->filterActivatedByTypeAndId(BaseModule::DELIVERY_MODULE_TYPE, $value)
->findOne();

if (null === $module) {
$context->addViolation(Translator::getInstance()->trans('Delivery module ID not found'));
} elseif (!$module->isDeliveryModule()) {
$context->addViolation(
sprintf(Translator::getInstance()->trans("delivery module %s is not a Thelia\Module\DeliveryModuleInterface"), $module->getCode())
);
}
}
}

For more information about field types you can refer to Symfony form type documentation

Usage in templates​

To display the form in your template you will need the form name, it is the name of your module in lowercase + full namespace and the class of your form in snake_case. For example the form name for YourModule\Form\SomethingForm.php will be yourmodule_form_something_form It can be modified with the static function getName but we do not advise to do that, because it's more simple to guess a form name by reading is namespace than going in to the class and looking the method. It also guarantees a unique name for your form.

Call your form​

First of all you have to call the form you need by using the form block :

{form name="yourmodule_form_something_form"}
...
{/form}

The form reference is now available in the $form variable.

Display it​

{form name="yourmodule_form_something_form"}
<form method="post" action="{url path='your/target'}" {form_enctype form=$form}>
...
</form>
{/form}

Displaying a form field​

Custom form field​

For displaying a field, you have to use the {form_field} block, and put the name of the field you want to display in the “field” parameter :

{form name="thelia_form_order_delivery_form"}
<form method="post" action="{url path='your/target'}" {form_enctype form=$form} >
{form_hidden_fields form=$form}

{form_field form=$form field="firstname"}
<label>{intl l="{$label}"}</label>
<input type="text" name="{$name}" value="{$value}" {$attr} />
{/form_field}

{form_field form=$form field="delivery_options"}
<select name="{$name}">
{foreach $choices as $choice}
<option value="{$choice->value}">{$choice->label}</option>
{/foreach}
</select>
{/form_field}
</form>
{/form}

Values available in the {form_field} block :

  • $name : field’s name used in the name part of your input
  • $value : default value to display
  • $data : the form definition data attribute
  • $type : the field type, as defined in the form definition (choice, radio, number, text, textarea, etc.)
  • $checked : the checked status (true / false) of a radio or checkbox field
  • $multiple : true if a select field may have multiple selected values
  • $disabled : true if the field is disabled, false otherwise
  • $read_only : true if the fiedl is read only, false otherwise
  • $max_length : the maximum length of the field
  • $required : true if the field is required, false otherwise
  • $label : label for this field, can be used in label html tag for example
  • $attr : all the attributes defined in your form class, can be any HTML attributes, such as an id, or any other attribute such as HTML5 form validation for example
  • $attr_list : the ‘attr’ array of form definition
  • $options : all the options available for this field. This variable is a PHP array.
  • $error : true if validation error has been detected on the field
  • $message : the error message, defined if $error is true, empty otherwise.
  • $choices : an array of available choices. $choices is available only if your field has defined choices.

Auto form field​

To speed up writing form in templates Thelia provide a Smarty plugin render_form_field which automatically generates the field HTML code, and all the related code, such as formatting and error reporting.

{form name="thelia_form_order_delivery_form"}
<form method="post" action="{url path='your/target'}" {form_enctype form=$form} >
{form_hidden_fields form=$form}

{render_form_field form=$form field="firstname"}
{render_form_field form=$form field="delivery_options"}
</form>
{/form}

Display errors​

If your form contains some errors, it automatically displays the value already sent by the user and then can display a message for each fields containing errors. The {form_field_error} is used, and it works like the {form_field} block. You can call it outside the {form_field} block :

{form name="thelia_form_order_delivery_form"}
<form method="post" action="{url path='your/target'}" {form_enctype form=$form} >
{form_hidden_fields form=$form}

{form_field form=$form field="firstname"}
{form_error form=$form.firstname}
{$message}
{/form_error}

<label>{intl l="{$label}"}</label>
<input type="text" name="{$name}" value="{$value}" {$attr} />
{/form_field}
</form>
{/form}

Hidden fields​

Thelia uses hidden fields internally. In order to display these fields (and all the hidden fields defined in your form), use the form_hidden_fields plugin.
Don’t forget this, as it contains the CRSF validation data :

{form name="thelia_form_order_delivery_form"}
<form method="post" action="{url path='your/target'}" {form_enctype form=$form} >
{form_hidden_fields form=$form}
...
</form>
{/form}

Usage in controllers​

Form are useful to validate data submitted by users. This is done by two functions in controllers :

  • createForm that create a form object
  • validateForm that validate form data
<?php

namespace Front\Controller;

class OrderController extends BaseFrontController
{
public function submitRoute()
{
$form = $this->createForm(OrderDeliveryForm::getName);

try {
$data = $this->validateForm($form)->getData();

// Do what you want with submitted data

} catch (\Exception $e) {
// Do something when the form is not valid
}
}
}