PHP/MySQL 预约/预约系统的最佳实践
Posted
技术标签:
【中文标题】PHP/MySQL 预约/预约系统的最佳实践【英文标题】:Best practice for PHP/MySQL Appointment/Booking system 【发布时间】:2013-06-03 12:26:07 【问题描述】:我需要一些人来为我目前正在从事的美发师的 php/mysql 预约系统争取“最佳实践”。希望我们可以一起清除一些事情,以避免事后重新做系统。我一直在查看 SO 和 Google 以获得一些教程、最佳实践等,但我没有找到任何符合我需求的东西。
基本信息
每天都有多名美发师可用,每位美发师都有自己的日程安排,其中包含他/她与客户的约会。与美发师相连的是一张表格,其中包含他/她在一周内有空的时间。
表格:人
+----+------+-------+-----------+
| id | name | email | available |
+----+------+-------+-----------+
| 1 | John | i@a.c | Y |
| 2 | Sara | c@i.a | N |
+----+------+-------+-----------+
表:次(这个表有一个主键,我把它排除在下面的计划之外)
+-----------+-------------+-----------+-----------+
| people_id | day_of_week | start | end |
+-----------+-------------+-----------+-----------+
| 1 | 1 | 08:00 | 12:00 |
| 1 | 1 | 12:30 | 17:00 |
| 1 | 3 | 09:00 | 12:00 |
| 1 | 4 | 10:30 | 16:00 |
| 1 | 5 | 09:00 | 17:00 |
| 1 | 6 | 09:00 | 12:00 |
| 2 | 1 | 09:00 | 12:00 |
| 2 | 2 | 09:00 | 12:00 |
| 2 | 3 | 09:00 | 12:00 |
+-----------+-------------+-----------+-----------+
正如您所见,人和时间之间存在一对多的关系(显然,因为一周有 7 天)。但除此之外,还可以选择在一天中的几个小时之间添加休息时间(请参阅 people_id = 1、day_of_week = 1:08:00-12:00 和 12:30-17:00)。
此外,还有一个名为“hairdress_types”的表,该表包含可以进行的各种类型的约会(如染发、剪发、洗头等)。此表包含此约会所需的时间(以分钟为单位)。
最后我有一张很简单的表appointments
:
id, people_id, types_id, sex, fullname, telephone, emailaddress, date_start, date_end
开始日期和结束日期将是 MySQL 中的完整 DATETIME 字段,从而更容易使用 MySQL 查询函数进行计算。
最佳做法是什么?
所以,按照我的设置方式,前端用户会在字段中选择一个日期,触发一个 ajax/jquery 函数,该函数会在所选日期查找所有可用的美发师。然后用户指定美发师(这不是强制性的:用户也可以选择“任何”美发师选项)和他/她想要进行的约会类型。
提交第一个表单后,可以使用以下信息:
-
日期(日、月、年)
people_id(如果选择了理发师,可以为 0 表示“任何”或 ID)
hairdress_type(与预约所需的分钟数相关联)
使用此信息,我会从选定的美发师中选择可用日期或我会循环显示所有可用的美发师及其可用日期。
这就是我精神崩溃的地方!因为检查可用日期的最佳方法是什么。我认为最好的方式是:
-
查询给定日期的理发师时间(一次 1 个)
使用 query1 结果的 startdate + 约会类型花费的分钟数查询约会表(如:
SELECT * FROM appointments WHERE ((date_start >= $start AND date_start <= ($start+$time)) OR (date_end > $start AND date_end <= ($start+$time)) AND people_id = 1
)
一旦没有找到结果,我就认为这个位置是免费的,并且作为一个选项提供给用户
我面临的更大问题是第 2 点:我对这个查询真的很疯狂,这是我需要找到与特定时间跨度匹配的约会的完整查询吗?
感谢您的阅读和思考! :-)
// 编辑:多一点“测试数据”:
约翰 - 星期一 - 12:00 - 17:00。 约会: - 12:00 - 12:30 - 14:30 - 15:30
一个用户想要一个需要 2 小时的约会,在上面的例子中我会检查:
-
12:00 到 14:00 之间有预约吗?是的,.. 前往下一个地点
14:00 到 16:00 之间有预约吗?是的,.. 前往下一个地点
16:00 到 18:00 之间有预约吗?错误,17:00 后不可用
因此.. 使用 10/15 分钟的“时间块”可能是更好的选择。进行检查:
-
12:00 - 14:00
12:10 - 14:10
12:20 - 14:20 等。
这将找到 12:30 到 14:30 之间的可用位置。
// 编辑 2:可能查询到第 2 步
我一直在写一些纸上的东西(一张有约会的桌子和可能使用的空位)。我想出了以下内容。无法预约的情况:
-
$start 和 $end 之间有 start_date 的约会
$start 和 $end 之间有 end_date 的约会
有一个约会 start_date $end
将上述内容与people_id
一起查询到约会表将导致没有行(= 空闲位置)或一个/多个行,在这种情况下,位置被占用。
我想找到空位的最好方法是查询数据库中 X 分钟的块,开始间隔为 10 分钟。这个解决方案的缺点是我每小时需要 6 个查询,每个美发师大约需要 48 个查询......关于如何减少查询量的任何想法?
【问题讨论】:
【参考方案1】:最后,我选择了一个为数据库中的开始日期和结束日期生成时间戳的系统。在检查时,我在开头加了一秒,从结尾减去一秒,以避免约会时间重叠。
我最终做了什么
显然,我不确定这是最佳做法,但它确实对我有用。用户首先选择他们的性别和当天的偏好。这会发送一个 AJAX 请求以获取可用的人员和各种预约类型(例如染发、剪发等)。
选择完所有设置(性别、日期、人员和类型)后,我首先进行一些简单的验证:检查日期,检查日期(“N”)是否不是 7(星期日)。如果一切正常,开始更重要的事情:
1) 约会类型是从数据库中获取的,包括该类型花费的总时间(30 分钟、45 分钟等) 2) 获取可用的个人(当天的完整人员列表,或者如果选择了一个人,则只获取一个人),包括他们的可用时间
人员(或一个人)然后循环,从他们自己的开始时间开始。此时我有一组数据包含:
$duration (of the appointment type)
$startTime (starting time of the person selected in the loop)
$endTime (= $startTime + $duration)
$personStart (= starting time of the person)
$personEnd (= end time of the person)
让我们来看看这个演示数据:
$duration = 30 min
$startTime = 9.00h
$endTime = 9.30h
$personStart = 9.00h
$personEnd = 12.00h
我在这里做的是:
while( $endTime < $personEnd )
// Check the spot for availability
$startTime = $endTime;
$endTime = $startTime + $duration;
显然,在这种情况下,它被简化了。因为当我检查可用性时,现场不是免费的。我将 $startTime 设置为等于找到的最新约会并在循环中从那里开始。
示例:
I check for a free spot at 9.00 but the spot is not free because there's an appointment from 9.00 till 10.00, then 10.00 is returned and $startTime is set to 10.00h instead of 9.30h. This is done to keep the number of queries to a minimum since there can be quiet a lot.
检查可用性功能
// Check Availability
public static function checkAvailability($start, $end, $ape_id)
// add one second to the start to avoid results showing up on the full hour
$start += 1;
// remove one second from the end to avoid results showing up on the full hour
$end -= 1;
// $start and $end are timestamps
$getAppointments = PRegistry::getObject('db')->query("SELECT * FROM appointments WHERE
((
app_start BETWEEN '".date("Y-m-d H:i:s", $start)."' AND '".date("Y-m-d H:i:s", $end)."'
OR
app_end BETWEEN '".date("Y-m-d H:i:s", $start)."' AND '".date("Y-m-d H:i:s", $end)."'
)
OR
(
app_start < '".date("Y-m-d H:i:s", $start)."' AND app_end > '".date("Y-m-d H:i:s", $end)."'
))
AND
ape_id = ".PRegistry::getObject('db')->escape($ape_id));
if(PRegistry::getObject('db')->num_rows($getAppointments) == 0)
return true;
else
$end = 0;
foreach(PRegistry::getObject('db')->fetch_array(MYSQLI_ASSOC, $getAppointments, false) as $app)
if($app['app_end'] > $end)
$end = $app['app_end'];
return $end;
由于我将约会存储为“从:10.00 到:11.00”,因此我必须确保检查 11:00:01 到 11:59:59 之间的地点,否则 11:00 的约会将显示在结果。
在函数结束时,如果找到约会,我循环结果并返回最新结束。这是我上面提到的循环中的下一个开始。
希望这对任何人都有帮助。正如 info:ape_id
是它所链接的“约会人”的 ID。
【讨论】:
您能否深入了解您使用的查询,或者您最终是否运行了大量查询以确定可用插槽? 我会在上面的答案中添加一些细节。无法真正给出完整的答案,但我尽量做到详细 谢谢!你为我节省了很多时间:) 之后你的预订系统有什么问题吗?具有讽刺意味的是,我也在为美发师建立一个预订系统。 如您所见,这是多年前的遗留代码。该系统一直正常工作,直到去年被更换。在 Laravel 中为另一个客户端进行了完全重建,但计算仍然有效(或多或少)【参考方案2】:使用 MySQL 关键字BETWEEN
。
SELECT * FROM mytable WHERE mydate BETWEEN start_date AND end_date;
如果您想查看从现在到一天之间是否有约会,您可以这样做:
$enddate = strtotime('+1 day', time());
SELECT * FROM mytable WHERE mydate BETWEEN NOW() AND $enddate;
Source
【讨论】:
好吧,这不会完全奏效,因为我没有一个日期要检查。有开始也有结束。在X分钟的时间跨度内发现其中任何一个,都不能预约。另一方面:如果没有找到开始,但在“开始”后 10 分钟找到了结束日期,我必须从第一个找到的结束日期开始再次检查......以上是关于PHP/MySQL 预约/预约系统的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章