DEPRECATION WARNING

This documentation is not using the current rendering mechanism and is probably outdated. The extension maintainer should switch to the new system. Details on how to use the rendering mechanism can be found here.

PHP cheat-sheets

Form model

  • Must implement Romm\Formz\Form\FormInterface (see line 11);
  • Can use the trait Romm\Formz\Form\FormTrait to implement the required methods (see line 13);
  • Must contain the “setters” and “getters” of each property.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php
namespace MyVendor\MyExtension\Form;

use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
use Romm\Formz\Form\FormInterface;
use Romm\Formz\Form\FormTrait;

/**
 * Example form
 */
class ExampleForm extends AbstractEntity implements FormInterface {

    use FormTrait;

    /**
     * @var string
     */
    protected $email;

    /**
     * @var string
     */
    protected $name;

    /**
     * @return string
     */
    public function getEmail(){
       return $this->email;
    }

    /**
     * @return string
     */
    public function getName(){
       return $this->name;
    }
}

Controller

  • Two actions are advised: one for the form displaying, one for its submission (see lines 11 & 21);
  • The submission action must indicate the object type: the name of the PHP class of the form (see line 21);
  • The submission action must indicate the form validator which will be used (see line 19).

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
namespace MyVendor\MyExtension\Controller;

use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use MyVendor\MyExtension\Form\ExampleForm;

class ExampleController extends ActionController {
    /**
     * Show an example form.
     */
    public function showFormAction()
    {
        // Do anything you need in here...
    }

    /**
     * Action called when the Example form is submitted.
     *
     * @param ExampleForm $exForm
     * @validate $exForm MyVendor.MyExtension:Form\ExampleFormValidator
     */
    public function submitFormAction(ExampleForm $exForm)
    {
        // The form is valid: should you save it? Process it? Your call!
    }
}

Form validator

  • Must inherit Romm\Formz\Validation\Validator\Form\AbstractFormValidator (see line 10);
  • Can manipulate $this->result, for instance to add errors (see line 65).
  • Can override the methods beforeValidationProcess() and afterValidationProcess(), which are called before and after the validation process (see lines 24 & 58);
  • Can call dynamic methods at the end of a field validation: *Validated where * is the field name in lowerCamelCase (see line 43);
  • Can de(activate) a field with the methods activateField() and deactivateField() (see lines 31 & 32).

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?php
namespace MyVendor\MyExtension\Validation\Validator\Form;

use Romm\Formz\Validation\Validator\Form\AbstractFormValidator;
use MyVendor\MyExtension\Utility\SimulationUtility;
use MyVendor\MyExtension\Utility\SessionUtility;
use MyVendor\MyExtension\Utility\GeographyUtility;
use MyVendor\MyExtension\Form\SimulationForm;

class ExampleFormValidator extends AbstractFormValidator {

    /**
     * @var SimulationForm
     */
    protected $form;

    /**
     * Before validation begins, we check if the user is still connected: if
     * not he will be automatically redirected.
     *
     * We also activate the rule `required` for the fields `name` and `first
     * name` if at least one of them is filled.
     */
    protected function beforeValidationProcess()
    {
        SessionUtility::checkUserIsConnected();

        if (empty($this->form->getName())
            && empty($this->form->getFirstName())
        ) {
            $this->deactivateFieldValidator('name', 'required');
            $this->deactivateFieldValidator('firstName', 'required');
        }
    }

    /**
     * When the zip code has been validated, we try to fetch the city which
     * matches this code. If no city was find we do nothing: the city value
     * submitted by the user will be validated next. If we find a city, we
     * fill the form with this new value and deactivate the field `city`,
     * because it is no more a user value.
     */
    protected function zipCodeValidated()
    {
        $zipCode = $this->form->getZipCode();
        $city = GeographyUtility::getCityFromZipCode($zipCode);
        if (null !== $city) {
            $this->form->setCity($city);
            $this->deactivateField('city');
        }
    }

    /**
     * If there was no error in the form submission, the simulation process
     * runs. If the simulation result contains errors, we cancel the form
     * validation.
     */
    protected function afterValidationProcess()
    {
        if (false === $this->result->hasErrors()) {
            $simulation = SimulationUtility::simulate($this->form);

            if (null === $simulation) {
                $error = new Error('Simulation error!', 1454682865)
                $this->result->addError($error);
            } else {
                $this->form->setSimulationResult($simulation);
            }
        }
    }
}

Validators

  • It is advised to use validators which inherit Romm\Formz\Validation\Validator\AbstractValidator; the main reason for that is to be able to use the property $javaScriptValidationFiles (see line 4). Otherwise, basic Extbase validators work;
  • Can associate JavaScript files with the property $javaScriptValidationFiles: these files contain a code adaptation of the validator in JavaScript (see line 10);
  • Can define messages which may be overridden in TypoScript with the property $supportedMessages (see line 25);
  • Also contains all basic Extbase validators features, like the property $supportedOptions (see line 17).

Example (from the core of FormZ):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php
namespace Romm\Formz\Validation\Validator;

class NumberLengthValidator extends AbstractValidator
{

    /**
     * @var array
     */
    protected static $javaScriptValidationFiles = [
        'EXT:formz/Resources/Public/JavaScript/Validators/Formz.Validator.NumberLength.js'
    ];

    /**
     * @var array
     */
    protected $supportedOptions = [
        'minimum' => [0, 'The minimum length to accept', 'integer'],
        'maximum' => [PHP_INT_MAX, 'The maximum length to accept', 'integer'],
    ];

    /**
     * @var array
     */
    protected $supportedMessages = [
        'default' => [
            'key'       => 'validator.form.number_length.error',
            'extension' => null
        ]
    ];

    /**
     * @inheritdoc
     */
    public function isValid($value)
    {
        $pattern = '/^[0-9]{' . $this->options['minimum'] . ',' . $this->options['maximum'] . '}$/';
        if (false === preg_match($pattern, $value)) {
            $this->addError(
                'default',
                1445862696,
                [$this->options['minimum'], $this->options['maximum']]
            );
        }
    }
}

Utilities

The class Romm\Formz\Utility\FormUtility contains methods that may help you during development:

Get form with errors

The function getFormWithErrors returns a form submitted during the last request, but which is not accessible from the controller because it contains errors.

Example:

<?php
namespace MyVendor\MyExtension\Controller;

use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use MyVendor\MyExtension\Form\ExampleForm;
use Romm\Formz\Utility\FormUtility;

class ExampleController extends ActionController {
    /**
     * Show an example form.
     */
    public function showFormAction()
    {
        $submittedForm = FormUtility::getFormWithErrors(ExampleForm::class);
        if (null !== $submittedForm) {
            $this->view->assign('submittedForm', $submittedForm);
        }
    }
}

Redirect an action if an argument is missing

Using Extbase, a user can try to access to the submission action, without actually submitting the form. For instance, he submits the form, then pastes the result URL in a new tab: Extbase will think the user submitted the form, but he didn't. In normal time, it would throw a fatal error.

FormZ provides the function onRequiredArgumentIsMissing, which will check that a required argument is missing, and run actions otherwise.

Example:

<?php
namespace MyVendor\MyExtension\Controller;

use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use MyVendor\MyExtension\Form\ExampleForm;
use Romm\Formz\Utility\FormUtility;

class ExampleController extends ActionController {
    /**
     * Show an example form.
     */
    public function showFormAction()
    {
        // Do anything you need in here...
    }

    /**
     * Function called before `submitFormAction()`.
     */
    public function initializeSubmitFormAction()
    {
        FormUtility::onRequiredArgumentIsMissing(
            $this->arguments,
            $this->request,
            function() {
                // If the argument `$exForm` is missing, we redirect to the
                // action "showForm".
                $this->redirect('showForm');
            }
        );
    }

    /**
     * Action called when the Example form is submitted.
     *
     * @param ExampleForm $exForm
     * @validate $exForm MyVendor.MyExtension:Form\ExampleFormValidator
     */
    public function submitFormAction(ExampleForm $exForm)
    {
        // The form is valid: should you save it? Process it? Your call!
    }
}