В большинстве случаев у вас будут формы, опирающиеся на сущности ORM (entities) и таблицы ORM или другие постоянные хранилища(peristent stores), но бывают случаи когда вам необходимо проверить действие пользователя, а затем выполнить действие, если данные действительны. Наиболее распространенным примером этого является контактная форма.
Как правило, при использовании класса Form вы хотите использовать подкласс для определения
вашей формы. Это упрощает тестирование и позволяет повторно использовать вашу форму.
Формы помещаются в src/Form и обычно имеют Form
в качестве суффикса класса.
Например, простая контактная форма будет выглядеть так:
// в src/Form/ContactForm.php
namespace App\Form;
use Cake\Form\Form;
use Cake\Form\Schema;
use Cake\Validation\Validator;
class ContactForm extends Form
{
protected function _buildSchema(Schema $schema)
{
return $schema->addField('name', 'string')
->addField('email', ['type' => 'string'])
->addField('body', ['type' => 'text']);
}
protected function _buildValidator(Validator $validator)
{
return $validator->add('name', 'length', [
'rule' => ['minLength', 10],
'message' => 'A name is required'
])->add('email', 'format', [
'rule' => 'email',
'message' => 'A valid email address is required',
]);
}
protected function _execute(array $data)
{
// Отправить письмо.
return true;
}
}
В приведенном выше примере мы видим, 3 защищённых(protected) метода:
_buildSchema
- используется для определения данных схемы, которые
используются FormHelper для создания HTML-формы. Вы можете определить
тип поля, длину и точность.
_buildValidator
- получает экземпляр Cake\Validation\Validator
,
к которому вы можете присоединить валидаторы.
_execute
- позволяет определить поведение, которое вы хотите выполнить,
когда вызывается execute()
и данные являются валидными.
Вы всегда можете определить дополнительные общедоступные методы, как вам это нужно.
После того, как вы определили форму, вы можете использовать её в своем контроллере, для обработки и проверки данных запроса:
// В контроллере
namespace App\Controller;
use App\Controller\AppController;
use App\Form\ContactForm;
class ContactController extends AppController
{
public function index()
{
$contact = new ContactForm();
if ($this->request->is('post')) {
if ($contact->execute($this->request->getData())) {
$this->Flash->success('Мы скоро свяжемся с вами.');
} else {
$this->Flash->error('Возникла проблема с отправкой вашей формы.');
}
}
$this->set('contact', $contact);
}
}
В приведенном выше примере мы используем метод execute()
для запуска метода _execute()
нашей формы только тогда, когда данные валидные, и соответственно устанавливают флеш-сообщения.
Мы могли бы также использовать метод validate()
только для проверки данных запроса:
$isValid = $form->validate($this->request->getData());
Чтобы установить значения для полей формы без моделей форм, можно определить значения
с помощью $this->request->data()
, как и во всех других формах, созданных FormHelper:
// В контроллере
namespace App\Controller;
use App\Controller\AppController;
use App\Form\ContactForm;
class ContactController extends AppController
{
public function index()
{
$contact = new ContactForm();
if ($this->request->is('post')) {
if ($contact->execute($this->request->getData())) {
$this->Flash->success('Мы скоро свяжемся с вами.');
} else {
$this->Flash->error('Возникла проблема с отправкой вашей формы.');
}
}
if ($this->request->is('get')) {
// Значения, например, из пользовательской модели.
$this->request->data('name', 'John Doe');
$this->request->data('email','[email protected]');
}
$this->set('contact', $contact);
}
}
Значения должны быть определены только в том случае, если методом запроса является GET-метод, иначе вы перезапишете предыдущие данные POST, которые могли быть неверными и не были сохранены.
Как только форма была проверена, вы можете получить от нее ошибки:
$errors = $form->errors();
/* $errors contains
[
'email' => ['Требуется валидный адрес электронной почты']
]
*/
Можно исключить отдельные поля из контроллера без использования класса Validator. Наиболее распространенным вариантом использования этого является проверка правильности работы на удалённом сервере. В таком случае вы должны вручную аннулировать поля, соответствующие обратной связи с удаленного сервера:
// в src/Form/ContactForm.php
public function setErrors($errors)
{
$this->_errors = $errors;
}
Согласно тому, как класс validator вернул бы ошибки, $errors
должен быть
в таком формате:
["fieldName" => ["validatorName" => "Отображаемое сообщение об ошибке"]]
Теперь вы сможете аннулировать поля формы, установив fieldName, а затем установить сообщения об ошибках:
// В контроллере
$contact = new ContactForm();
$contact->setErrors(["email" => ["_required" => "Ваш адрес электронной почты"]]);
Перейдите к созданию HTML с помощью FormHelper, чтобы увидеть результаты.
Создав класс Form, вы, скорее всего, захотите создать для него HTML-форму. FormHelper понимает объекты формы, подобные объектам ORM:
echo $this->Form->create($contact);
echo $this->Form->control('name');
echo $this->Form->control('email');
echo $this->Form->control('body');
echo $this->Form->button('Submit');
echo $this->Form->end();
Вышеизложенное создало бы HTML-форму для ContactForm
, которую мы определили ранее.
HTML-формы, созданные с помощью FormHelper, будут использовать определенную схему и
валидатор для определения типов полей, максимальной длинны и ошибок проверки(валидации).