Form classes - markstory/cakephp GitHub Wiki
The Problem
There is no natural way to handle non-datastore backed forms. In previous versions of CakePHP we had access to $useTable = false;
for this scenario. Ideally, we'd like to avoid re-introducing this awkward abstraction, and instead focus on providing a solution that better fits the use cases.
Use Cases
- Creating contact us forms.
- Creating forms that feed into remote service calls.
- Creating forms that don't directly expose ORM backed models. Eg. forms that abstract or have a layer of indirection around the domain model and actions being performed.
Loose requirements
In order to play nicely with the rest of CakePHP a solution should have:
- A way to define 'schema' for the form. This will be used to inform FormHelper on how to build forms.
- A way to define validation rules for form data.
- A way to perform an 'action' with form data once it has been validated. This action will always be user defined.
Proposed API
I'm proposing that we build upon the successes we've had with the Validator and Database\Schema API's. We can leverage those in this new context to provide consistent experiences for developers. Defining a Form class could look like:
namespace App\Form;
use Cake\Form\Form;
class ContactForm extends Form
{
public function buildSchema($schema)
{
// Could also be addColumn
$schema->addField('name', ['type' => 'string', 'length' => 255])
->addField('email', ['type' => 'string'])
->addField('comment', ['type' => 'text']);
return $schema;
}
public function buildValidator($validator)
{
$validator
->add('email', 'format', [
'rule' => 'email',
'message' => 'must be a valid email'
])
->requirePresence('name')
->requirePresence('comment');
return $validator;
}
public function execute()
{
// Do things with valid data.
}
}
Using a form from a controller would work similar to using an ORM table:
// Less verbose API
$form = new ContactForm();
if ($form->process($this->request->data())) {
// Success!
} else {
$errors = $form->errors();
}
Likewise using a form with the FormHelper should be easy:
// In a controller
$form = new ContactForm();
$this->set('form', $form);
// In the template
echo $this->Form->create($form);
echo $this->Form->input('name');
echo $this->Form->input('email');
echo $this->Form->input('comment');
echo $this->Form->button('send');
echo $this->Form->end();
The above will probably result in the following classes being created:
- Cake\Form\Form - The base class for forms.
- Cake\Form\Schema - The schema class for forms.
- Cake\View\Form\FormContext - A context implementation for forms.
In addition it will re-use the existing validator features.