Flick
Guide Validation Services API Pro Examples GitHub
Docs / Features

Prebuilt Forms

Flick includes 4 ready-to-use form templates for common scenarios. These forms come with fields, validation rules, and custom error messages already configured.

Quick Reference

Form Fields Description
/login username, password Basic login form
/shortContact name, email, body Simple contact form
/registration username, email, password, password-confirm, agree User registration with password confirmation
/example 20+ fields Comprehensive demo of all field types

Usage

Loading a Prebuilt Form

Pass the form path to the create() method:

$form = new Flick\Flick();
echo $form->create('/login');

Overriding Attributes

You can override any form attribute by passing an array as the second parameter:

echo $form->create('/login', [
    'action' => '/auth/login',
    'button' => 'Sign In',
    'id' => 'my-login-form'
]);

Only the keys you name change; everything else comes from the form file.

Tip

Copying the file into your own assets/forms/ directory is the cleaner option when you always want the same changes. See Customize.

Handling Submissions

Use the request() method to retrieve and validate form data:

if ($form->submitted()) {
    $data = $form->request('/login');

    if ($form->ok()) {
        // Validation passed. File-loaded forms return a list of one-key arrays,
        // so flatten it before reaching in by name.
        $data = array_merge(...$data);
        $username = $data['username'];
        $password = $data['password'];
    } else {
        // Validation failed
        $errors = $form->getErrors();   // ['username' => 'Please enter your username', ...]
    }
}

Warning

Check $form->ok(), not $data. request('/login') returns an array either way — it's populated with whatever was posted even when validation failed, so a truthy $data tells you nothing about validity.

Use getErrors() to read the error bag. errors() is a different method: it prints an alert box and returns nothing.

Form id and submitted()

Each prebuilt form file sets its own form id (form-login, form-contact, form-registration, form-example), and submitted() only returns true when the posted _id matches the instance's current id. Calling create('/login') updates the instance id, so either call create() before you check submitted(), or pass the form's id in the config (new Flick\Flick(['id' => 'form-login'])) when you handle the submission first. With neither, submitted() stays false and the handler never runs.


Login Form (/login)

A simple two-field login form.

echo $form->create('/login');

Fields

Field Type Validation Error Message
username text required "Please enter your username"
password password required "Please enter your password"

Form Attributes

Attribute Value
ID form-login
Method POST
Button "Login"

Full Definition

[
    'action' => '/',
    'method' => 'POST',
    'attributes' => [
        'id' => 'form-login'
    ],
    'button' => [
        'text' => 'Login'
    ],
    'fields' => [
        'username' => [
            'type' => 'text',
            'name' => 'username',
            'label' => 'Username',
            'rules' => ['required'],
            'messages' => [
                'required' => 'Please enter your username',
            ]
        ],
        'password' => [
            'type' => 'password',
            'name' => 'password',
            'label' => 'Password',
            'rules' => ['required'],
            'messages' => [
                'required' => 'Please enter your password'
            ]
        ]
    ]
]

Common Customizations

Change the action and button text:

echo $form->create('/login', [
    'action' => '/auth/signin',
    'button' => 'Sign In'
]);

Add a "Remember Me" checkbox:

You'll need to create a custom form or use field elements to add additional fields.


Contact Form (/shortContact)

A simple 3-field contact form with email validation.

echo $form->create('/shortContact');

Fields

Field Type Validation Error Message
name text required, min:5 "Please enter your name"
email email required, email "Please enter your email address" / "Please enter a valid email address"
body textarea required "Please enter your message"

Form Attributes

Attribute Value
ID form-contact
Method POST
Button "Submit form"

Full Definition

[
    'action' => '/',
    'method' => 'POST',
    'attributes' => [
        'id' => 'form-contact'
    ],
    'button' => [
        'text' => 'Submit form'
    ],
    'fields' => [
        'name' => [
            'name' => 'name',
            'label' => 'Name',
            'rules' => ['required', 'min:5'],
            'messages' => [
                'required' => 'Please enter your name',
            ]
        ],
        'email' => [
            'type' => 'email',
            'name' => 'email',
            'label' => 'Email',
            'rules' => ['required', 'email'],
            'messages' => [
                'required' => 'Please enter your email address',
                'email' => 'Please enter a valid email address'
            ]
        ],
        'body' => [
            'type' => 'textarea',
            'name' => 'body',
            'label' => 'Message',
            'rules' => ['required'],
            'messages' => [
                'required' => 'Please enter your message',
            ]
        ],
    ]
]

Complete Example with Email

$form = new Flick\Flick([
    // form files carry their own id ('form-contact' here); set it in the config
    // so submitted() recognizes the POST before create() has run
    'id' => 'form-contact',
    'services' => [
        'mail' => [
            'fromAddress' => 'noreply@example.com',
            'mailer' => [
                'transport' => 'smtp',
                'host' => 'smtp.example.com',
                'port' => 587,
                'encryption' => 'tls',
                'username' => 'user@example.com',
                'password' => 'secret'
            ]
        ]
    ]
]);

// Handle submission first
if ($form->submitted()) {
    // a list of one-key arrays, so flatten it before sending
    $data = array_merge(...$form->request('/shortContact'));

    if ($form->ok()) {
        $sent = $form->mail->sendFormData(
            'admin@example.com',
            'New Contact Form Submission',
            $data
        );

        if ($sent) {
            $form->successMessage('Thank you for your message!');
        } else {
            $form->errorMessage('Sorry, your message could not be sent.');
        }
    }
}

// Create the form
$form->create('/shortContact', ['action' => '/contact']);

Registration Form (/registration)

A complete user registration form with password confirmation and terms agreement.

echo $form->create('/registration');

Fields

Field Type Validation Error Message
username text required, min:3, max:20, slug Various
email email required, email "Please enter your email address" / "Please enter a valid email address"
password password required, min:8, hash "Please enter a password" / "Your password must be at least 8 characters"
password-confirm password required, matches:password "Please confirm your password" / "Your passwords do not match"
agree checkbox required "You must agree to the Terms"

Form Attributes

Attribute Value
ID form-registration
Method POST
Button "Sign Up"

Full Definition

[
    'action' => '/',
    'method' => 'POST',
    'attributes' => [
        'id' => 'form-registration'
    ],
    'button' => [
        'text' => 'Sign Up'
    ],
    'fields' => [
        'username' => [
            'type' => 'text',
            'name' => 'username',
            'label' => 'Username',
            'rules' => ['required', 'min:3', 'max:20', 'slug'],
            'messages' => [
                'required' => 'Please enter a username',
                'min' => 'Username must be at least 3 characters',
                'max' => 'Username cannot be more than 20 characters'
            ]
        ],
        'email' => [
            'type' => 'email',
            'name' => 'email',
            'label' => 'Email',
            'rules' => ['required', 'email'],
            'messages' => [
                'required' => 'Please enter your email address',
                'email' => 'Please enter a valid email address'
            ]
        ],
        'password' => [
            'type' => 'password',
            'name' => 'password',
            'label' => 'Password',
            'rules' => ['required', 'min:8', 'hash'],
            'messages' => [
                'required' => 'Please enter a password',
                'min' => 'Your password must be at least 8 characters'
            ]
        ],
        'confirm' => [
            'type' => 'password',
            'name' => 'password-confirm',
            'label' => 'Confirm Password',
            'rules' => ['required', 'matches:password'],
            'messages' => [
                'required' => 'Please confirm your password',
                'matches' => 'Your passwords do not match'
            ]
        ],
        'agree' => [
            'type' => 'checkbox',
            'name' => 'agree',
            'label' => 'I agree to the Terms',
            'value' => '1',
            'rules' => ['required'],
            'messages' => ['required' => 'You must agree to the Terms']
        ]
    ]
]

Important Notes

Password Hashing

The hash rule automatically hashes the password using PHP's password_hash() function. When you retrieve the form data, the password will already be hashed and ready to store in your database.

Slug Conversion

slug is a modifier, not a validation rule — it doesn't reject anything, it rewrites the value. Spaces and hyphens become underscores, accented letters are transliterated to ASCII (ée), and anything else that isn't a letter, digit, or underscore is dropped. Gern Blanston! is stored as Gern_Blanston. That keeps the username safe for URLs and database queries, but the value you save is not always the value the user typed.

Complete Example

$form = new Flick\Flick();

echo $form->create('/registration', ['action' => '/register']);

if ($form->submitted()) {
    // a list of one-key arrays, so flatten it before reading fields by name
    $data = array_merge(...$form->request('/registration'));

    if ($form->ok()) {
        // $data['password'] is already hashed by the `hash` modifier
        $form->sql->save('users', [
            'username' => $data['username'],
            'email' => $data['email'],
            'password' => $data['password']
        ]);

        echo 'Registration successful!';
    }
}

Tip

The confirmation field is named password-confirm with a hyphen, so it arrives as $data['password-confirm'].


Example Form (/example)

A comprehensive form demonstrating all field types and features. Useful for testing and learning.

echo $form->create('/example');

Form Attributes

Attribute Value
ID form-example
Method POST
Multipart Yes (for file uploads)
Class needs-validation
Button "Submit Me" (with btn-lg class)

Field Inventory

This form includes the following field types:

Text Inputs:

  • text - Basic text input with help text
  • email - Email input
  • password - Password input
  • password-confirm - Password confirmation

Other Inputs:

  • textarea - Multi-line text
  • number - Numeric input
  • tel - Telephone number
  • url - URL input
  • date - Date picker
  • time - Time picker
  • color - Color picker
  • week - Week picker
  • month - Month picker
  • range - Range slider (0-100)

File Uploads (in fieldset):

  • photo - Single file upload (image only)
  • photos[] - Multiple file upload (images only)

Select Menus (in fieldset):

  • state - Uses prebuilt states dropdown
  • foobarBaz - Custom inline options
  • fruit[] - Multiple select

Radio & Checkbox (in fieldset):

  • radio - Radio button group
  • radio-inline - Inline radio buttons
  • agree - Single checkbox

Full Definition

[
    'action' => '/',
    'method' => 'POST',
    'attributes' => [
        'id' => 'form-example',
        'multipart' => true,
        'class' => 'needs-validation',
        'string' => 'novalidate'
    ],
    'button' => [
        'text' => 'Submit Me',
        'attributes' => [
            'class' => 'btn-lg'
        ]
    ],
    'fields' => [
        // ... (see source file for complete definition)
    ]
]

Using as a Learning Tool

The example form is a great way to see how different field types work:

// Render the form to see all field types
echo $form->create('/example');

// Inspect the submitted data
if ($form->submitted()) {
    $data = $form->request('/example');
    var_dump($data);                    // a list of one-key arrays
    var_dump(array_merge(...$data));    // flattened into name => value
}

The example form includes file-upload fields, so submitting it requires the Upload service to be configured with a directory — add 'services' => ['upload' => ['directory' => 'uploads']] to your config, or submitting will throw a "please specify an upload directory" exception.

Tip

You can find the complete form definition in vendor/flickphp/flick/lang/en/forms/example.php or view it in the GitHub repository.


Creating Custom Forms

Need a form that isn't included? You have two options:

  1. Create a custom form file - See the Customize documentation
  2. Build forms with field elements - See Creating Forms

Custom Form File Structure

Create a PHP file that returns an array:

// myFlickAssets/forms/myForm.php
return [
    'action' => '/submit',
    'method' => 'POST',
    'attributes' => [
        'id' => 'my-custom-form'
    ],
    'button' => [
        'text' => 'Submit'
    ],
    'fields' => [
        'field_name' => [
            'type' => 'text',
            'label' => 'Field Label',
            'rules' => ['required'],
            'messages' => [
                'required' => 'This field is required'
            ]
        ]
    ]
];

Then load it with:

echo $form->create('/myForm');