【发布时间】:2014-08-09 10:40:32
【问题描述】:
我有一张名为 Bookings 的表。此表包含表示为特定服务进行的预订的数据,其中包含许多变量。
不久前,我遇到了当前数据结构的问题,即任何影响时间、日期或价格的预订更改都会影响其他相关的财务记录、日期的预订列表等。
当时我的解决方案是创建一个修改表来跟踪对预订所做的任何更改。然后,每当 Booking 模型被要求返回预订时,它都会添加所做的修改(在 afterFind()Cake 回调中)并呈现最新版本的预订,类似这样(请原谅 Paint 绘图):
当您要求 Booking 模型返回预订 #1234 时,此方法可以正常工作。它返回预订的最新表示,包括所有修改(相互叠加),包括一个包含所有修改和原始预订数据以供参考的数组。
我的问题是我最近意识到我需要能够使用自定义条件查询这个模型,如果其中一个条件在其中一个修改中实现,结果将不会' 不匹配,因为模型正在搜索原始记录而不是最终呈现的记录。我查询模型以返回 abc 为蓝色(非灰色)的行的示例:
在该示例中,模型直接查看 abc 为蓝色的行的原始数据,并且不返回此结果,因为蓝色值位于 之后附加的修改中找到原始结果。
我现在所做的是将查询放入 Booking 模型的 beforeFind() 回调,以查找符合给定条件的修改,加入预订以确保任何其他条件仍然匹配。当它在上面的示例中返回蓝色时,它将结果存储在一个数组中作为类属性并继续使用常规的find(),但排除该预订的 ID 不会被返回(因为我们发现它的更新版本)。然后它将它们合并在一起,在afterFind() 中再次对它们进行排序等。
这行得通,虽然我希望它有点冗长。
毕竟,我意识到在此应用程序的其他部分中,有些模型手动加入预订表并搜索预订。所以现在我需要一种方法,能够将修改合并到所有这些手动连接中,直接连接到 MySQL 中的表,而不影响原始数据,最好不要更改太多代码。
我的想法是我需要删除手动连接并改为创建模型关联。当我查询拥有Many Bookings 的Customer 模型(将修改应用于每个预订)时,Booking 模型的beforeFind() 和afterFind() 是否仍会运行?
我的另一个选择是通过删除可能包含在修改中的任何条件从 MySQL 返回更多的行,然后使用 PHP 根据我的搜索条件过滤结果。这个选项让我有点害怕,因为如果没有这个标准,结果集可能会很大......
如何实现这种数据结构?我的关键需求仍然是我不想更改原始的Booking记录,而是在顶部添加Modification记录,但我需要能够通过模型查询预订(包括修改)。
我想尝试尽可能多地将这种集成保留在幕后,这样我就不必通过整个应用程序来更改 n 的查询数量,如下所示:
$get_blue = $this->Booking->find('all', array(
'conditions' => array(
'Booking.abc' => 'blue'
)
));
我希望能够隐式包含对预订所做的任何修改,以便在上述查询中返回最新的预订。
另一个问题是当 Booking 模型手动加入搜索查询时,如下所示:
$get_transactions_on_blue_bookings = $this->Transaction->find('all', array(
'joins' => array(
array(
'table' => 'sql_bookings_table', // non-standard Cake format, I know - it's an example
'alias' => 'Booking',
'type' => 'LEFT',
'conditions' => 'Booking.booking_id = Transaction.booking_id'
)
),
'conditions' => array(
'Booking.abc' => 'blue'
)
));
如您所见,上面的查询不会包含我上面MSPaint示例中的修改,因为它是在SQL中手动加入表(修改集成在Booking的before和afterFind()回调函数中型号)。
对此的任何帮助将不胜感激。
编辑
我知道这已经够长了,但我想补充一点,我想跟踪这些变化而不更新原始记录的原因是 财务 方面无法改变,因为它会影响报告。
到目前为止,我能看到的最快和最简单的解决方案是在所有情况下直接对原始预订应用修改,除非它影响财务信息,但仍将其作为修改进行跟踪(因为我目前不需要基于搜索关于此信息)。
【问题讨论】:
-
我们最近遇到了一个类似的问题,即不适合用途的旧数据结构。我们尝试了您在此处使用的方法,即在顶部添加一个层来处理更改,但它最终产生了太多错误。最后,我们从头开始重新设计数据结构,并编写了一个 CLI 导入器来移动所有现有数据。这样做意味着我们可以慢慢地将面向客户端的功能迁移到新系统中,因为这两个系统都在跟踪数据。当我们对新系统完全满意时,我们只需从项目中删除遗留代码。希望对您有所帮助。
-
@orciny 确实有帮助。我认为我们最终也将不得不重新设计其工作方式。
标签: php mysql cakephp database-design cakephp-1.3