0

現在のクライアントのイベント情報を取得するために、別のウェブ会社が作成したデータベースにアクセスしています。私のクライアントは、イベントの情報を入力し、日付が繰り返されるかどうかをメモします。すべての定期的な日付を表示しようとしています。これまでのところ、定期的な日付と定期的な日付のすべてを表示することができました。

テーブルは次のように配置されます。

  • イベント
  • Events_Recurring

これはイベント テーブルの一部ですBIGGER PICTURE

イベント テーブル

Events_Recurring テーブルは次のようになります。

イベント定期テーブル

クライアントが繰り返しとしてチェックすると、events_recurring テーブルは、イベント ID と、イベントが繰り返される曜日や月などのその他の情報を含む行を作成します。

繰り返し発生する特定の ID の倍数を表示する方法がわかりません。アクセスできる開始日と終了日、およびそれが繰り返される曜日があります。

たとえば、このイベントが毎週木曜日に再発したとします。1 月 1 日に開始し、1 月 31 日に終了することはわかっていましたが、それを実行して、1 月の毎週木曜日の日付で 4 つの異なるイベントを吐き出すことができますか?

これが私が取り組んでいる完全なコードです。これを理解しようとしている間は少し面倒です。底に向かって再発をチェックしています

// Access external database
$events_db = new wpdb(TOP SECRET CREDENTIALS HERE);
$events_db->show_errors();

if ($events_db) :
    // Query Events Database
    $events = $events_db->get_results(
        "
        SELECT ID, RequestDateStart, RequestDateEnd, Ministry, RequestTimeStart, EventName, CoordinatorName, EventDescription, Location
        FROM gc_events
        WHERE PrivateEvent = 0
        AND Ministry = 15
        AND date(RequestDateStart)>=date(NOW())
        ORDER BY RequestDateStart
        "
    );

    // Create the event data that will be displayed
    foreach ($events as $event) :

        // Store Event ID in a variable
        $masterID = $event->ID;

        echo '<div class="col-12">';

        echo '<strong>ID:</strong> ' . $event->ID . '<br /><strong>Event Name:</strong> ' . $event->EventName . '<br /><strong>Leader:</strong> ' . $event->CoordinatorName . '<br /><strong>Date:</strong> ' . date('l, F j',strtotime($event->RequestDateStart)) . '<br /><strong>Start Time:</strong> ' . date('g:i a',strtotime($event->RequestTimeStart));

        // CHECK IF RECURRING

        $recurring_events = $events_db->get_results(
            "
            SELECT gc_event_id, period, day
            FROM gc_event_recurring
            WHERE gc_event_id = '$masterID'
            "
        );

        foreach ($recurring_events as $recurring_event) :
        if ($recurring_event->period === 'week') {

        echo '<div class="col-12"><strong>&uarr; WEEKLY</strong><br />';

        echo $recurring_event->day;

        echo '</div>';

        }
        endforeach;

        echo '</div>';

    endforeach;
endif;

私が今得ている結果(定期的なイベントで)は

イベント: 毎週の祈り
日付: 2013 年 2 月 1 日

私が望む結果は

イベント: 毎週の祈り
日付: 2013 年 2 月 1 日

イベント: 毎週の祈り
日付: 2013 年 2 月 8 日

イベント: 毎週の祈り
日付: 2013 年 2 月 15 日

イベント: 毎週の祈り
日付: 2013 年 2 月 22 日


これは、開始日が 2 月 1 日で、終了日が 2 月 28 日の場合です。

4

2 に答える 2

12

アドバイスの一言。

繰り返しパターンの「説明」を格納するデータベースを設計することは、設計の観点からは非常にクリーンなアプローチですが、途中で多くの問題が発生する可能性があります。

私はしばらく前に同様のアプローチでプロジェクトを実行しました(データベース設計を調べてそれを回答に追加します)。繰り返し発生するイベントの正確な日時を再現することはできましたが、次のことに遭遇します。次の状況での問題。ほとんどはこれに由来します:

繰り返し発生するイベント繰り返しパターンを表すため、実際の(個々の)イベントはデータベース内の物理的な記録ではありません

  1. 顧客が新しいイベントを追加することを決定した場合、それが既存のイベントと重複していないかどうかをどのように確認しますか?繰り返しパターンに基づいて、すべての「イベント」を計算する必要があります。
  2. イベントのスケジュール時刻を変更する必要があるとお客様が判断した場合、過去のイベントではなく、将来のすべてのイベントにこの変更をどのように適用しますか(元のイベントを複製し、その終了を変更する必要があります) -日付、および複製されたイベントを新しい開始日で設定します)
  3. 顧客が繰り返しパターンから1日を削除したい場合(たとえば、1つのイベントがキャンセルされた場合)、元のイベントを2つの別々の繰り返しに分割する、「キャンセル/ブロック」された日付/時刻を設定する必要があります。テーブル
  4. 特定のイベントを「予約」する必要がある場合、データベースに物理的に存在しないため、個々のイベントを「実際の」イベントレコードに添付することはできません。たとえば、単一のイベントを再スケジュールまたはキャンセルできるかどうかを確認するには、データベースが外部キー制約を使用して関連する予約を自動的に更新できないため、コードからこれを行う必要があります。
  5. パフォーマンスについて; 個々のイベントは物理的に保存されないため、表示するたびに計算する必要があります。データベースに1000回の定期的なイベントがあることを検討し、2年後の23週目の「カレンダー」を表示してみてください。すべての定期的なイベントのパターンを分析し、それらが生成するすべてのイベントを計算する必要があります。

もちろん、すべてはシステムの実際の使用法に依存しますが、私たちが遭遇した問題について警告したいと思います。

'schedules'テーブルのスキーマは次のとおりです(定期的なイベントパターンが含まれています)。

CREATE TABLE IF NOT EXISTS `schedules` (
  `id`              int(11)     NOT NULL auto_increment,
  `date_start`      date        NOT NULL,
  `time_start`      time        NOT NULL,
  `time_end`        time        NOT NULL,
  `recur_until`     date        default NULL COMMENT 'end date when recurrence stops',
  `recur_freq`      varchar(30) default NULL COMMENT 'null, "secondly", "minutely", "hourly", "daily", "weekly", "monthly", "yearly"',
  `recur_interval`  smallint(5) unsigned default NULL COMMENT 'e.g. 1 for each day/week, 2 for every other day/week',
  `recur_byday`     smallint(5) unsigned default NULL COMMENT 'BITWISE; monday = 1, sunday = 64',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

説明されている問題を回避する方法

これらの問題の解決策を完全に説明することはおそらくここでは適切ではありませんが、考慮すべきことがいくつかあります。

それ自体で説明されているように定期的なイベントを保存することは悪い習慣ではありません。イベントがいつ、どのくらいの頻度で行われるべきかを完全に説明しています。ただし、実際のイベントの物理的な記録がないことが問題の原因です。

  1. 定期的なイベントを作成または変更する場合は、結果のすべてのイベントを計算し、それらを物理レコードとして保存します。これらのレコードを照会したり、「予約」を添付したりして、外部キー制約などのデータベース機能を利用してレコードを適切に処理できるようになります。
  2. 1.で説明したように個々のイベントを保存するときは、それらが属する「スケジュール」への参照を保持していることを確認してください。(たとえば)顧客が定期的なイベントの時間を変更したい場合は、関連するすべての(個別の)イベントを更新できます。
  3. 状況2では、おそらく将来のイベントのみを更新する必要があるため、それを実現するには、「定期的なイベント」を2つに「分割」する必要があることに注意してください。この場合、「将来の」イベントを新しい「定期的なイベント」にアタッチする必要があり、古いイベントは既存の「定期的なイベント」にアタッチされたままになります。

データベース/ソフトウェアの設計に時間を費やし、設計が達成しようとしていることに対して「機能する」かどうかを適切に調査します。それをテストし、物事を試してみてください。うまくいかない場合は、「捨てる」ことを躊躇しないでください。多くの場合、物事を「修正」するよりも、最初から始める方が簡単です。適切な設計には時間がかかり、正しくするためにいくつかの「再設計」が必要になる場合がありますが、最終的には時間とお金を節約できます。

これがお役に立てば幸いです。

于 2013-02-02T08:40:53.677 に答える
1
        foreach ($events as $event) :

                // Store Event ID in a variable
                $masterID = $event->ID;

                echo '<div class="col-12">';

                echo '<strong>ID:</strong> ' . $event->ID . '<br /><strong>Event Name:</strong> ' . $event->EventName . '<br /><strong>Leader:</strong> ' . $event->CoordinatorName . '<br /><strong>Date:</strong> ' . date('l, F j',strtotime($event->RequestDateStart)) . '<br /><strong>Start Time:</strong> ' . date('g:i a',strtotime($event->RequestTimeStart));

                // CHECK IF RECURRING

                $recurring_events = $events_db->get_results(
                    "
                    SELECT gc_event_id, period, day
                    FROM gc_event_recurring
                    WHERE gc_event_id = '$masterID'
                    "
                );

                foreach ($recurring_events as $recurring_event) :
                if ($recurring_event->period == 'week') {
                $StartDate = strtotime($event->RequestDateStart);
                $EndDate = strtotime($event->RequestDateEnd);
$TotalDays = round(($EndDate-$StartDate)/(60*60*24*7));
                for($i = 0 ;$i<($TotalDays-1);$i++)
                {
                $StartDate += (60*60*24*7);
                echo '<div class="col-12">';

                echo '<strong>ID:</strong> ' . $event->ID . '<br /><strong>Event Name:</strong> ' . $event->EventName . '<br /><strong>Leader:</strong> ' . $event->CoordinatorName . '<br /><strong>Date:</strong> ' . date('l, F j',$StartDate) . '<br /><strong>Start Time:</strong> ' . date('g:i a',strtotime($event->RequestTimeStart));


                }


                }
                endforeach;

                echo '</div>';

            endforeach;

これを試して、うまくいくかどうか教えてください

于 2013-02-02T07:58:42.740 に答える