无模型表单

class Cake\Form\Form

大多数情况下,您的表单将由 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 以查看结果。

使用 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 表单将使用定义的模式和验证器来确定字段类型、最大长度和验证错误。