在CakePHP3中混淆验证与应用程序规则

时间:2015-06-27 10:55:19

标签: validation cakephp-3.0 cakephp-3.1 cakephp-3.x

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

我已多次阅读食谱中的章节(123),但老实说,我并不了解如何以正确的方式做到这一点。我也知道目前有一个issue/discussion at 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

根据cookbook"确保电子邮件的唯一性"是应用程序规则的用例。

// 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时才会触发错误。但也可以检查验证中的唯一性。为什么不以这种方式做得更好?

// 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 - 调用后操纵实体时,我也看不到或理解两个独立验证状态的好处。

如果我自动向实体添加一些值,我想确保在将它们保存到数据库之前值仍然有效(如在CakePHP2中)。所以我猜它总是 Using Validation as Application Rules更好/ nessecary?!

你如何处理这个问题?是否有其他示例可用于显示/演示Validation与ApplicationRules的好处和一些用例?

1 个答案:

答案 0 :(得分:6)

我认为您混淆的主要原因是您不知道$parent.$index如果已经包含错误,则不会保存实体。例如:

save()

它将返回false的原因是因为$entity = $users->newEntity(['email' => 'not an email']); $users->save($entity); // Returns false 在继续实际保存过程之前读取save()结果。因此,在调用$entity->errors()之前,不需要手动检查错误,就像手册中的示例所示。

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

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

由于validation*()很少在数据库事务中发生,因此没有实际保证在验证和保存电子邮件之间仍然是唯一的。这是应用程序规则试图解决的问题之一:应用程序规则在与保存过程的其余部分相同的事务中运行,因此任何支持都会有一致性保证。

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

相关问题