Лучшие практики для PHP/MySQL Appointment/ Система бронирования

Мне нужно, чтобы некоторые люди боролись с "лучшей практикой" для системы встреч 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

Начало и конец даты будут полными полями DATETIME в MySQL, что облегчит вычисление с использованием функций запросов MySQL.

Какая лучшая практика?

Таким образом, как я настраивал, пользователь внешнего интерфейса выбирал дату в поле, запускающем функцию ajax/jquery, которая находит всех парикмахеров, доступных на выбранную дату. Затем пользователь указывает парикмахера (это не обязательно: пользователь также может выбрать вариант "Любой" для парикмахера) и тип встречи, которую он / она хочет сделать.

После отправки первой формы можно использовать следующую информацию:

  1. дата (день, месяц и год)
  2. people_id (может быть 0 для "Любой" или ID, если был выбран парикмахер)
  3. hairress_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. Мой ум действительно сходит с ума по этому запросу. Это полный запрос, который мне нужен, чтобы найти встречи, соответствующие определенному временному интервалу?

Спасибо за чтение и размышления!:-)

// Edit: немного больше "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_date между $ start и $ end
  2. Существует встреча с end_date между $ start и $ end
  3. Есть встреча с start_date <$ start и end_date> $ end

Запрос вышеупомянутого к таблице назначений вместе с people_id приведет к тому, что ни одна строка (= свободное место) или одна / несколько строк, в этом случае место берется.

Я думаю, что лучший способ найти открытые места - это запросить у базы данных блоки X минут с интервалом запуска 10 минут. Плохая сторона этого решения заключается в том, что я буду получать по 6 запросов в час, то есть около 48 запросов на каждого парикмахера... Есть идеи, как уменьшить это количество запросов?

2 ответа

Решение

В конце концов я выбрал систему, которая генерировала временные метки для даты начала и окончания в базе данных. Во время проверки я добавил одну секунду в начало и вычел одну секунду из конца, чтобы избежать совпадения времени для встреч.

Что я в итоге делал

Очевидно, я не уверен, что это лучшая практика, но она сработала для меня. Пользователь начинает с выбора своего пола и предпочтений на день. Это отправляет запрос 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 идентификатор "Назначенного лица", с которым он связан.

Используйте ключевое слово 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};

Источник

Другие вопросы по тегам