Class: Form

Form is an elegant form handling class. It provides validation of the form referrer, request method, cross-site request forgery (CSRF) prevention, and numerous convenience functions for validating form submissions and input data. Also integrates with the /js/jquery.verify_values.js jQuery plugin to provide matching client-side validation based on the same set of rules.

The input validation can be useful not just for form submissions, but it's packaged here to keep things tidy.

Simplest usage:

<?php

$form = new Form ('post', $this);

echo $form->handle (function ($form) {
    // Create some data...
    $foo = new MyModel ($_POST);
    $foo->put ();

    // Refer them to a thank you page
    $form->controller->redirect ('/thank/you');
});

?>

Long form usage:

<?php

$form = new Form ('post', 'apps/myapp/forms/verify.php');

if ($form->submit ()) {
    // handle form
    info ($_POST);

} else {
    // set some default values
    $obj = new StdClass;
    $obj->foo = 'bar';

    // merge with user input
    $obj = $f->merge_values ($obj);

    // get failed fields
    $obj->failed = $form->failed;

    // add scripts for client-side validation
    $page->add_script ('<script src="/js/jquery.verify_values.js"></script>');
    $page->add_script ('<script>
        $(function () {
            $.verify_values ({
                element: "#myapp-form",
                handler: "myapp/verify",
                callback: function (failed) {
                    // highlight the failed elements
                }
            });
        });
        </script>');

    // output your form template
    echo $tpl->render ('myapp/form', $obj);
}

?>

Properties

public $failed = array ()

Fields that failed validation.

public $method = 'post'

The required request method.

public $rules = array ()

Validation rules.

private $_rules

The original $form_rules passed to the constructor, parsed down to the appname/rules short form.

public $view = false

A view to render the form with. Used by handle().

public $data = false

A data object with the initial form values. Used by handle().

public $controller = false

An optional copy of the controller object.

public $verify_referrer = true

Whether to verify the referrer or not.

public $verify_csrf = true

Whether to verify with a CSRF token or not.

public $csrf_token

Token generated for CSRF prevention.

public $csrf_field_name = '_token_'

The name of the token form field.

public $error = false

The reason submit() failed to pass.

public $invalid = array ()

The full details of which rules failed in a call to Validator::validate_list().

public $js_validation = true

Whether handle() should include the default JavaScript validation or just the /js/jquery.verify_values.js script so you can write your own custom validation display.

Methods

public __construct ($required_method = 'post', $form_rules = false, $controller = false)

Constructor method. Parameters are:

  • Required request method (default is 'post')
  • A reference to the form rules file, or a Controller object
  • If param 2 is a file reference, this can be the Controller object

Usage:

<?php

$f = new Form (); // defaults and no Controller or rules set
$f = new Form ('post'); // POST requests but no Controller or rules
$f = new Form ('post', $this); // POST and Controller set
$f = new Form ('post', 'myapp/rules'); // POST and rules set
$f = new Form ('post', 'myapp/rules', $this); // Everything set

?>

Note that if the rules are not set but the Controller is passed, the rules file will be assumed to match the appname/handlername of the currently active handler, and the view will be set to match as well. This is the most handy scenario, since if you match your rules file, handler, and view names, you can simply say:

<?php

$f = new Form ('post', $this);

?>

And it will set everything up correctly based on $this->uri in the Controller.

public handle ($func)

Accepts an anonymous function (aka closure) that handles the form submission, and abstracts away the rendering of the form based on the provided rules and view, helping eliminate much of the boilerplate code of form creation.

Note that handle() will also include /js/jquery.verify_values.js for you, but you need to provide your own initialization code to perform the client-side validations. There is a page in the public wiki on www.elefantcms.com describing the steps for this.

Also note that if the anonymous function returns false, there will be no output and the false status will be passed to the handler to catch.

public submit ()

Check if the form is okay to submit. Verifies the request method, the referrer, and the input data.

public failed ($field)

Mark a field having failed and return false. Usage:

if ($some_validation_condition === false) {
    return $form->failed ('field-name');
}

public merge_values ($obj)

Merge the values from $_GET or $_POST onto a data array or object for re-rendering a form with the latest data entered.

public verify_request_method ()

Verify the request method is the one specified.

public verify_referrer ()

Verify the referrer came from this site. No remote form submissions, since those are almost certainly abusive.

public timeshift ()

Returns a time value to apply to CSRF tokens in order to impose a time limit on a generated token. Not usually needed directly, but rather used internally by generate_csrf_token() and verify_csrf().

public generate_csrf_token ($timeshift = false, $uri = '')

Generate a CSRF token and return it for custom use cases.

public initialize_csrf ($timeshift = false, $uri = '', $form_id = '')

Generate and initialize the CSRF token.

public generate_csrf_script ($form_id = '')

Generate the script that will append the token to forms in the page. You do not need to call this directly as long as you have {{ tail|none }} in your layout template, since initialize_csrf() will automatically add this to the tail if it can.

public verify_csrf ($uri = '')

Verify the CSRF token is present, matches the generated value. Tokens generated by generate_csrf_token() with a default timeshift value should be valid for between 120 and 180 minutes, depending on how close to the hour the initial form request was generated.

public static verify_value ($value, $type, $validator = false)

Alias of Validator::validate().

public verify_values ($values, $validations = array ())

Alias of Validator::validate_list().

public static checkbox ($name, $value, $label, $data)

Generate a checkbox in a template:

<?= Form::checkbox ('subscribe', 'yes', __ ('Join the spamotron!'), $data) ?>

This will generate the following HTML, with the checked attribute dependent on the value in $data->{$name}:

<label>
    <input type="checkbox" name="subscribe" value="yes" checked>
    Join the spamotron!
</label>

Also correctly handles names with square braces, e.g., options[one]

public static radio ($name, $value, $label, $data)

Generate a radio button in a template:

<?= Form::radio ('options', 'yes', __ ('Yes'), $data) ?>

This will generate the following HTML, with the checked attribute dependent on the value in $data:

<label>
    <input type="radio" name="options" value="yes" checked>
    Yes
</label>

public static text ($name, $data, $size, $type = 'text')

Generate a text input in a template:

<?= Form::text ('name', $data, 20) ?>

This will generate the following HTML:

<input type="text" name="name" value="Value from $data" size="20">

public static textarea ($name, $data, $cols, $rows)

Generate a text input in a template:

<?= Form::textarea ('name', $data, 50, 4) ?>

This will generate the following HTML:

<textarea name="name" cols="50" rows="4">Value from $data</textarea>

public static option ($value, $label, $actual)

Generate a radio button in a template:

<?= Form::option ('yes', __ ('Yes'), $data->select_name) ?>

This will generate the following HTML, with the selected attribute dependent on the value in $data->{$name}:

<option value="yes" selected>Yes</option>