7

关于验证的多个问题可能属于一起,因为它们都在处理 CakePHP 3 中的新验证概念。

我已经多次阅读食谱中的章节(1、2、3 但老实说,我不明白如何以正确的方式去做。我也知道目前在 GitHub 上有一个关于 CakePHP3 中的验证的问题/讨论,它可能涉及相同的主题。

验证错误被触发,例如使用 patchEntity。因此,我认为在执行保存操作之前始终检查/显示错误会更好:

// src/Controller/UsersController.php
public function add() {
  $user = $this->Users->newEntity();
  if ($this->request->is('post')) {
    $user = $this->Users->patchEntity($user, $this->request->data, ['validate' => 'default'] );
    if ( $user->errors() ) {
      $this->Flash->error('There was a Entity validation error.');
    } else {
      // Optional: Manipulate Entity here, e.g. add some automatic values
      // Be aware: Entity content will not be validated again by default
      if ( $this->Users->save($user) ) {
        $this->Flash->succeed('Saved successfully.');
        return $this->redirect(['controller' => 'Users', 'action' => 'index']);
      } else {
        $this->Flash->error('Not saved - ApplicationRule validation error.');
      }
    }
  }
  $this->set('user', $user);
}

为什么食谱教程$user->errors()在保存数据之前不使用?据我了解,save如果已经存在验证错误,则不需要调用它?!另一种方法是结合错误检查和保存操作:

if ( !$user->errors() && $this->Users->save($user) ) {
  $this->Flash->succeed('Saved successfully.');
  return $this->redirect(['controller' => 'Users', 'action' => 'index']);
} else {
  $this->Flash->error('There was a validation OR ApplicationRule error.');
}

你在用这个吗?我应该使用它吗?或者如果不是,为什么不呢?

为什么即使我没有$user->errors()在控制器中使用 CakePHP 也会显示验证错误,就像在所有食谱示例中一样?我以为save不会检查实体验证?!

示例:isUnique

根据食谱, “确保电子邮件唯一性”是应用程序规则的一个用例。

// src/Model/Table/UsersTable.php
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\ORM\RulesChecker;
use Cake\ORM\Rule\IsUnique;
// Application Rules
public function buildRules(RulesChecker $rules) {
  $rules->add($rules->isUnique(['email'], 'This email is already in use'));
  return $rules;
}

该错误只能通过save控制器中的 -call 触发。但也可以在验证中检查唯一性。为什么不这样做更好?

// src/Model/Table/UserTable.php
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;
public function validationDefault(Validator $validator) {
  $validator
    ->add('email', [
      'unique' => [
        'rule' => 'validateUnique',
        'provider' => 'table',
        'message' => 'This email is already in use'
        ],
      ])
  return $validator;
}

如果我可以在验证中添加 ApplicationRule,为什么我会/应该使用 ApplicationRules?

我如何在 ApplicationRule 中定义规则何时应仅应用于特定操作(并非所有创建/更新调用)?

patchEntity当在-call之后操作实体时,我也没有看到或理解两个单独的验证状态的好处。

如果我自动向实体添加一些值,我想确保这些值在将它们保存到数据库之前仍然有效(如在 CakePHP2 中)。所以我想总是 使用验证作为应用程序规则更好/必要?!

你一般如何处理这个问题?是否有其他示例可用于显示/展示验证与应用程序规则的好处和一些用例?

4

1 回答 1

5

我认为您的主要困惑来源是您不知道save()如果实体已经包含错误,它将不会保存实体。例如:

$entity = $users->newEntity(['email' => 'not an email']);
$users->save($entity); // Returns false

它将返回 false 的原因是因为在继续实际保存过程之前save()读取了结果。$entity->errors()因此,无需在调用 之前手动检查错误save(),就像手册中的示例所示。

电子邮件唯一性示例有点棘手,因为您要检查面向用户的表单(验证的目标)和应用程序规则。

重要的是要记住Validation,就像在validation*()方法中一样,用于向人类提供有关他们提供的数据的反馈。您想在保存过程开始之前在表单中显示所有错误(包括嵌套属性的错误)。

由于Validation很少发生在数据库事务中,因此无法真正保证在验证和保存电子邮件之间仍然是唯一的。这是应用程序规则试图解决的问题之一:应用程序规则确实与保存过程的其余部分在同一事务中运行,因此那里的任何检查都将具有一致性保证。

应用程序规则解决的另一个问题是它们可以处理已经在实体上设置的数据,因此您可以完全访问对象的当前状态。在修补实体或创建新实体时这是不可能的,因为任何传递的数据都可能不一致。

于 2015-06-27T20:14:00.187 回答