PHP / MySQL预约/预订系统的最佳实践

时间:2013-06-07 08:52:58

标签: php mysql appointment date-math

我需要一些人为我正在研究的理发师的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(如果选择理发师,则可以为“任意”或ID)0。
  3. hairdress_type(与预约所需的分钟数相关联)
  4. 使用这些信息,我会从选定的理发师中选择可用的日期我会为可用的美发师及其可用日期进行循环。

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

    1. 查询给定日期(每次1个)的理发师时间
    2. 使用query1结果的开始日期+约会类型所用的分钟数量来查询约会表(所以: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. 一旦找不到结果,我认为该地点是免费的,这是作为用户选项提供的
    4. 我面临的大问题是第2点:我的想法在这个查询上真的很疯狂,这是我需要找到匹配特定时间跨度的约会的完整查询吗?

      感谢阅读&amp;一起思考! : - )

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

      约翰 - 周一 - 12:00-17:00。 约会:   - 12:00至12:30   - 14:30 - 15:30

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

      1. 12点到14点之间有预约吗?是的,..继续下一个地点
      2. 14:00到16:00之间有预约吗?是的,..继续下一个地点
      3. 16:00至18:00之间有预约吗?错误,17:00后无法使用
      4. 因此......使用10/15分钟的“时间块”可能是更好的选择。进行检查:

        1. 12:00 - 14:00
        2. 12:10 - 14:10
        3. 12:20 - 14:20等..
        4. 这将在12:30到14:30之间找到可用的地点。

          //编辑2:对第2步的Possbile查询

          我一直在纸上制作一些东西(一张有预约和可能空白点的桌子)。我想出了以下内容。如果不能预约:

          1. 预约start_date BETWEEN $ start和$ end
          2. 预约end_date BETWEEN $ start和$ end
          3. 预约start_date&lt; $ start和end_date&gt; $结束
          4. 将上述内容与people_id一起查询到约会表将导致没有行(=自由点)或一行/多行(在这种情况下,该点被拍摄)。

            我想找到空位的最佳方法是在数据库中查询X分钟的块,开始间隔为10分钟。这个解决方案的不好的一面是,我会每小时查询6个查询,这对每个理发师来说都是大约48个查询...有关如何减少查询量的任何想法吗?

2 个答案:

答案 0 :(得分: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的预约将显示在结果。

在函数结束时,如果找到约会,我循环结果并返回最新结束。这是我在上面提到的循环中的下一个开始。

希望这对任何人都有帮助。正如信息:ape_id是与其链接的“约会人”的ID。

答案 1 :(得分: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};

Source