2

私が現在取り組んでいる美容院の PHP/MySQL 予約システムの「ベスト プラクティス」と戦ってくれる人が必要です。うまくいけば、後でシステムをやり直す必要がないように、一緒にいくつかの問題を解決できます。いくつかのチュートリアル、ベスト プラクティスなどについて SO と Google を見てきましたが、自分のニーズに合ったものは見つかりませんでした。

基本情報

毎日複数の美容師が利用できます。各美容師は、顧客との予定を含む独自の議題を持っています。美容師に接続されているのは、その美容師が週に利用できる時間を含むテーブルです。

表:人

+----+------+-------+-----------+
| id | name | email | available |
+----+------+-------+-----------+
| 1  | John | i@a.c | Y         |
| 2  | Sara | c@i.a | N         |
+----+------+-------+-----------+

テーブル: times (このテーブルには主キーがあります。以下のスケジュールから除外しました)

+-----------+-------------+-----------+-----------+
| 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     |
+-----------+-------------+-----------+-----------+

ご覧のとおり、人と時間の間には 1 対多の関係があります (明らかに、1 週間は 7 日なので)。しかし、それ以外にも、1 日の時間の間に休憩を追加するオプションもあります (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 ('Any' の場合は 0、または美容師が選択されている場合は ID)
  3. hairdress_type (予約にかかる分数にリンクされています)

この情報を使用して、選択した美容師から利用可能な日付を選択するか、利用可能なすべての美容師とその利用可能な日付をループします

これは私の心が精神的に崩壊する場所です!利用可能な日付を確認する最良の方法は何ですか。私が最善だと思った方法は次のとおりです。

  1. 指定された日付の美容師の時間を照会します (一度に 1 つずつ)
  2. 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) 。
  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_date が $start と $end の間にある予定があります
  2. $start と $end の間に end_date の予定があります
  3. start_date < $start and end_date > $end の予定があります

上記を一緒に予定表に照会すると、people_id行がない (= フリー・スポット) か、1 つまたは複数の行になり、その場合はスポットが使用されます。

オープン スポットを見つける最善の方法は、10 分の開始間隔で X 分のブロックをデータベースにクエリすることだと思います。このソリューションの悪い面は、1 時間ごとに 6 つのクエリを必要とすることです。これは、美容師ごとに約 48 クエリになります...そのクエリの量を減らす方法についてのアイデアはありますか?

4

2 に答える 2

1

最終的に、データベース内の開始日と終了日のタイムスタンプを生成するシステムに行き着きました。チェック中に、予定の重複時間を避けるために、開始に 1 秒追加し、終了から 1 秒を減算しました。

私は結局何をしたのですか

明らかに、これがベストプラクティスであるかどうかはわかりませんが、私にとってはうまくいきました。ユーザーは、性別とその日の好みを選択することから始めます。これにより、AJAX リクエストが送信され、利用可能な担当者とさまざまな種類の予定 (髪を染める、髪を切るなど) が取得されます。

すべての設定 (性別、日付、人物、タイプ) が選択されたら、いくつかの簡単な検証から始めます。日付を確認し、日付 ("N") が 7 (日曜日) でないかどうかを確認します。すべてが問題なければ、より重要な作業が開始されます。

1) 予約タイプは、このタイプにかかった合計時間 (30 分、45 分など) を含めてデータベースから取得されます。 1 つが選択されます) 利用可能な時間を含む

個人 (または 1 人) は、自分の開始時刻からループされます。この時点で、次を含む一連のデータがあります。

$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;
     } 
}

予定を「From:10.00 Till: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;

現在から 1 日の間に予約が空いているかどうかを確認するには、次のようにします。

$enddate = strtotime('+1 day', time());

SELECT * FROM mytable WHERE mydate BETWEEN NOW() AND {$enddate};

ソース

于 2013-06-07T08:59:39.267 に答える