2

我需要一些人为我目前正在研究的美发师的 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 函数,该函数会在所选日期查找所有可用的美发师。然后用户指定美发师(这不是强制性的:用户也可以选择“任何”美发师选项)和他/她想要进行的约会类型。

提交第一个表单后,可以使用以下信息:

  1. 日期(日、月、年)
  2. people_id(如果选择了理发师,则可以为 0 表示“任何”或 ID)
  3. hairdress_type(与约会所需的分钟数相关联)

使用此信息,我要么从选定的美发师中选择可用日期,要么循环所有可用的美发师及其可用日期。

这就是我的思想精神崩溃的地方!因为检查可用日期的最佳方法是什么。我认为最好的方式是:

  1. 查询给定日期的理发师时间(一次 1 次)
  2. 使用查询1结果的开始日期+约会类型花费的分钟数查询约会表(所以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:)
  3. 一旦没有找到结果,我就认为这个位置是免费的,并且作为一个选项提供给用户

我面临的更大问题是第 2 点:我对这个查询真的很疯狂,这是我需要找到与特定时间跨度匹配的约会的完整查询吗?

感谢您的阅读和思考!:-)

// 编辑:多一点“testdata”:

约翰 - 星期一 - 12:00 - 17:00。约会: - 12:00 - 12:30 - 14:30 - 15:30

用户想要一个需要 2 小时的约会,在上面的示例中,我会检查:

  1. 12:00 到 14:00 之间有预约吗?是的,.. 前往下一个地点
  2. 14:00 到 16:00 之间有预约吗?是的,.. 前往下一个地点
  3. 16:00 到 18:00 之间有预约吗?错误,17:00 后不可用

因此.. 使用 10/15 分钟的“时间块”可能是一个更好的选择。进行检查:

  1. 12:00 - 14:00
  2. 12:10 - 14:10
  3. 12:20 - 14:20 等。

这将在 12:30 和 14:30 之间找到可用的位置。

// 编辑 2:对第 2 步的可能查询

我一直在纸上写一些东西(一张有约会的桌子和可能使用的空位)。我想出了以下内容。以下情况不能预约:

  1. 在 $start 和 $end 之间有一个与 start_date 的约会
  2. 在 $start 和 $end 之间有一个 end_date 的约会
  3. 有一个约会 start_date < $start and end_date > $end

将上述内容与约会表一起查询people_id将导致没有行(= 空闲位置)或一个/多个行,在这种情况下,该位置被占用。

我想找到空缺点的最好方法是在数据库中查询 X 分钟的块,开始间隔为 10 分钟。这个解决方案的不好的一面是我每小时需要 6 个查询,每个美发师大约需要 48 个查询......关于如何减少查询量的任何想法?

4

2 回答 2

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。

于 2013-10-08T14:22:52.763 回答
0

使用 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};

资源

于 2013-06-07T08:59:39.267 回答