我有一个应用程序,我需要在CakePHP 3中验证营业时间,以确保它们不会重叠。所有记录都可以在一个表单中更改。数据看起来有点像这样:
| 标识符|日间|打开时间|关闭时间|
| - -|- -|- -|- -|
| 一个|一个|上午8时00分00秒|13点00分|
| 2个|一个|16点00分|22点00分|
现在,当我将第一个opening_time更改为17:00时,这将是无效的,因为它将与第二行重叠。但当我将第二个opening_time更改为18:00时,它应该是有效的。
我尝试使用buildRules:
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['store_id'], 'Stores'));
$rules->add(
function (BusinessHour $entity, array $options): bool {
$conditions = [
'id !=' => $entity->id,
'store_id' => $entity->store_id,
'day' => $entity->day,
'OR' => [
[
'opening_time <=' => $entity->opening_time,
'closing_time >=' => $entity->opening_time,
],
[
'opening_time <=' => $entity->closing_time,
'closing_time >=' => $entity->closing_time,
],
[
'opening_time >=' => $entity->opening_time,
'opening_time <=' => $entity->closing_time,
],
[
'closing_time >=' => $entity->opening_time,
'closing_time <=' => $entity->closing_time,
]
]
];
return !$options['repository']->exists($conditions);
},
'overlapping',
[
'errorField' => 'opening_time',
'message' => __('Business hours may not overlap.'),
]
);
return $rules;
}
但它会根据数据库中的数据检查第一条记录,并将其标记为无效,即使更改第二行会使其有效。例如,当数据库中的数据如上所述,我有以下帖子数据,它应该是有效的,但实际上不是。
$data['business_hours'] = [
(int) 0 => [
'day' => '0',
'opening_time' => [
'hour' => '16',
'minute' => '30'
],
'closing_time' => [
'hour' => '17',
'minute' => '00'
]
],
(int) 1 => [
'day' => '0',
'opening_time' => [
'hour' => '18',
'minute' => '00'
],
'closing_time' => [
'hour' => '20',
'minute' => '00'
]
],
];
我应该如何处理这个问题?
1条答案
按热度按时间biswetbf1#
从逻辑上讲,您一次只能保存一个实体,不仅在应用程序级别,而且在DBMS级别也是如此,因此该规则告诉您数据无效是正确的,因为它一次只能验证一个实体。
我认为您需要某种状态来处理此问题,或者需要验证和应用程序规则的混合,即您需要验证无状态数据以及有状态/持久化数据,不仅非持久化数据集中的所有小时都需要彼此有效,而且它们还需要相对于数据库中已持久化的数据有效。
我想,对于如何最好地解决这个问题,还有很大的讨论空间,在应用程序规则中还没有允许验证多个实体的接口,因此,无论如何解决这个问题,它可能是某种妥协/变通办法。
由于这最终是关于数据库中的数据,所有的验证都应该在事务中进行,所以我想最好在应用程序规则中保留一些内容。(并因此保存)yet,这样,后续检查将针对已经持久化的先前实体运行,这意味着最终您将针对彼此检查所有记录的有效性。
这里有一个例子--我不知道你的关联设置,所以我假设你保存的是
Stores
和关联的BusinessHours
,但是具体的设置并不重要,它应该只显示如何构建和传入自定义选项:它是一个
ArrayObject
示例是很重要的,这样它的状态在每个营业时间实体的多个不同的save()
调用中都将保持不变。因此,这是未经测试的,理想情况下它会工作,但它主要是为了说明我所说的内容。还请注意,我已经减少了打开/关闭时间条件,假设关闭时间必须大于打开时间,此检查理论上应涵盖所有可能的重叠。