大多数情况下,您的表单将由 ORM 实体 和 ORM 表 或其他持久存储支持,但有时您需要验证用户输入,并在数据有效时执行操作。最常见的示例是联系表单。
通常在使用 Form 类时,您会希望使用子类来定义您的表单。这使得测试更容易,并让您能够重复使用您的表单。表单被放置在 src/Form 中,并且通常以 Form
作为类后缀。例如,一个简单的联系表单将如下所示:
// in 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): Schema
{
return $schema->addField('name', 'string')
->addField('email', ['type' => 'string'])
->addField('body', ['type' => 'text']);
}
public function validationDefault(Validator $validator): Validator
{
$validator->minLength('name', 10)
->email('email');
return $validator;
}
protected function _execute(array $data): bool
{
// Send an email.
return true;
}
}
在上面的示例中,我们看到了表单提供的 3 个钩子方法
_buildSchema
用于定义 FormHelper 用于创建 HTML 表单的模式数据。您可以定义字段类型、长度和精度。
validationDefault
获取一个 Cake\Validation\Validator
实例,您可以向其附加验证器。
_execute
允许您定义当调用 execute()
并且数据有效时想要发生的行为。
您也可以根据需要随时定义其他公共方法。
定义好表单后,您可以在控制器中使用它来处理和验证请求数据
// In a controller
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('We will get back to you soon.');
} else {
$this->Flash->error('There was a problem submitting your form.');
}
}
$this->set('contact', $contact);
}
}
在上面的示例中,我们使用 execute()
方法仅在数据有效时运行表单的 _execute()
方法,并相应地设置闪存消息。如果我们想要使用非默认验证集,我们可以使用 validate
选项
if ($contact->execute($this->request->getData(), 'update')) {
// Handle form success.
}
此选项也可以设置为 false
以禁用验证。
我们也可以使用 validate()
方法来只验证请求数据
$isValid = $form->validate($this->request->getData());
// You can also use other validation sets. The following
// would use the rules defined by `validationUpdate()`
$isValid = $form->validate($this->request->getData(), 'update');
您可以使用 setData()
方法为无模型表单设置默认值。使用此方法设置的值将覆盖表单对象中的现有数据
// In a controller
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('We will get back to you soon.');
} else {
$this->Flash->error('There was a problem submitting your form.');
}
}
if ($this->request->is('get')) {
$contact->setData([
'name' => 'John Doe',
'email' => '[email protected]'
]);
}
$this->set('contact', $contact);
}
}
值应该只在请求方法为 GET 时定义,否则您将覆盖之前的 POST 数据,这些数据可能包含需要更正的验证错误。您可以使用 set()
来添加或替换单个字段或字段的子集
// Set one field.
$contact->set('name', 'John Doe');
// Set multiple fields;
$contact->set([
'name' => 'John Doe',
'email' => '[email protected]',
]);
表单验证后,您可以从中检索错误
$errors = $form->getErrors();
/* $errors contains
[
'name' => ['length' => 'Name must be at least two characters long'],
'email' => ['format' => 'A valid email address is required'],
]
*/
$error = $form->getError('email');
/* $error contains
[
'format' => 'A valid email address is required',
]
*/
可以从控制器中使单个字段失效,而无需使用 Validator 类。这最常见的用例是在远程服务器上进行验证时。在这种情况下,您必须根据远程服务器的反馈手动使字段失效
// in src/Form/ContactForm.php
public function setErrors($errors)
{
$this->_errors = $errors;
}
根据验证器类返回错误的方式,$errors
必须采用以下格式
['fieldName' => ['validatorName' => 'The error message to display']]
现在,您可以通过设置 fieldName 来使表单字段失效,然后设置错误消息
// In a controller
$contact = new ContactForm();
$contact->setErrors(['email' => ['_required' => 'Your email is required']]);
继续使用 FormHelper 创建 HTML 以查看结果。
创建好 Form 类后,您可能希望为其创建一个 HTML 表单。FormHelper 理解 Form 对象,就像理解 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();
以上代码将为我们之前定义的 ContactForm
创建一个 HTML 表单。使用 FormHelper 创建的 HTML 表单将使用定义的模式和验证器来确定字段类型、最大长度和验证错误。