CakePHP 3.x:将应用程序规则应用于多个实体 问题
我有一个关于如何最好地在一个表上实现业务规则的问题,该表应该应用于在相互了解的情况下创建的实体。从我到目前为止的研究来看,我怀疑这与CakePHP的内部工作方式相违背,并且我很可能错过了框架的另一个特性,允许这样做 所涉及的实体有一个CakePHP 3.x:将应用程序规则应用于多个实体 问题,cakephp,cakephp-3.0,Cakephp,Cakephp 3.0,我有一个关于如何最好地在一个表上实现业务规则的问题,该表应该应用于在相互了解的情况下创建的实体。从我到目前为止的研究来看,我怀疑这与CakePHP的内部工作方式相违背,并且我很可能错过了框架的另一个特性,允许这样做 所涉及的实体有一个关联,通过它可以保存数据。例如,UsersTable和调查问卷通过UsersQuestionnairesTable关联。因此,我注意到UsersQuestionnairesTable的buildRules方法运行n次,其中n是正在创建的关联实体的数量 目标 我的目标
关联,通过它可以保存数据。例如,UsersTable
和调查问卷
通过UsersQuestionnairesTable
关联。因此,我注意到UsersQuestionnairesTable
的buildRules
方法运行n
次,其中n
是正在创建的关联实体的数量
目标
我的目标是应用一个构建规则,确保请求数据中的UsersQuestionnaire
行中的一行(并且只有一行)被标记为default:true
如果用户不存在其他UsersQuestionnairesTable
记录
目前的结果实际上是,通过在UsersQuestionnairesTable::buildRules
中应用此方法,在尝试创建一个用户
时,通过UsersQuestionnairesTable
与一些问卷
关联,只有当它封送到实体中的有效负载的第一个数据行具有default:true
时,它才会通过验证。因此,它不适用于多实体创建,因为它将在第二行失败,因为默认值:false
,因此不会创建用户
我所理解/尝试的
据我所知,Table
类的buildRules
方法是实施应用于实体的应用程序逻辑规则的有用地方。例如,电子邮件在数据库中是唯一的
从
当验证确保数据的形式或语法正确时,规则侧重于将数据与应用程序和/或网络的现有状态进行比较
这些类型的规则通常称为“域规则”或“应用程序规则”。CakePHP通过在实体持久化之前应用的“RuleSchecker”公开了这个概念。一些域规则示例如下:
- 确保电子邮件的唯一性
- 状态转换或工作流步骤(例如,更新发票状态)
- 防止修改软删除的项目
- 强制执行使用率/费率上限
我希望在创建过程中对实体应用类似的规则,但了解请求数据中的其他实体,这样我就可以访问正在创建的所有UsersQuestionnairesTable
实体,以检查它们的deafult
值,如果没有发现true
,使功能失效,且无法创建所有实体
目前,在创建过程中但在保存之前应用于每个实体的此条件规则(尽管不正确)应说明所需的最终目标
用户质询可重新启动:
public function buildRules(RulesChecker $rules)
{
$enforceFirstAsDefault = function ($entity) {
$count = $this->find('all')
->where(['UserQuestionnaires.user_id' => $entity->user_id])
->andWhere(['Questionnaires.type_id' => 1])
->contain(['Questionnaires'])->count();
if ($count == 0 && !$this->containsDefault($entity)) {
return false;
}
return true;
};
$rules->add($enforceFirstAsDefault, [
'errorField' => 'no_default_identified',
'message' => 'A default questionnaire is required')
]);
}
...
private function containsDefault($entities): bool
{
foreach ($entities as $entity) {
if ($entity->is_default) {
return true;
}
}
return false;
}
由于希望在创建之前失败,模型上的
buildRules认为将此逻辑定位为仅适用于此模型的最合适位置,如下所示:
- 行为更适合模型之间的常见行为
- 虽然您可以使用
访问$event->getData()
封送前
中的数据,但我知道此方法更适合于 在持久化之前进行数据操作,因此可能不合适 为了我的需要李>
- 在许多可能负责创建
记录(无论是直接创建还是通过关联创建)的控制器中使用此功能感觉不那么枯燥 和SRP,因为它需要UsersQuestionnaires
(例如)了解并基于 取决于用户::create
有效负载数据中的行是否包含UsersQuestionnaires
,而不管它是否由某种可重用的帮助器包装李>default:true
- 在许多可能负责创建
buildRules
可以检查作为此请求一部分的所有实体,这样validaiton只有在创建了所有实体后才会失败或通过,我是否缺少什么
也许是一种用更多请求上下文覆盖/重载
构建规则的方法?或者这种业务逻辑更适合于另一个位置还是使用框架的不同功能?您的规则函数可以采用第二个参数,该参数接收传递给save
函数的选项。所以在你的控制器里
$this->UsersQuestionnaires->saveMany($entities, ['entities' => $entities]);
然后在你的桌子上:
$enforceFirstAsDefault = function ($entity, $options) {
// Use $options['entities'] here to access the set of entities being saved
}
很好,谢谢你。不知道从save
中筛选出的内容以及规则。你能链接到烹饪书/API文档中详细说明这一点的章节吗?如果这是我在旅行中错过的东西,我会向你道歉,但是谢谢你花时间来帮助我!是的,我没有看到规则、验证或保存部分中明确提到的连接。在文档存储库中提出可能是一个好问题?