使用PHP显示SQL数据库中的重复日期

时间:2013-02-02 07:04:05

标签: php mysql

我正在访问由其他网络公司创建的数据库,以检索当前客户端的事件信息。我的客户输入事件信息,并注明日期是否重复。我正在尝试显示所有重复日期。到目前为止,我已经能够显示所有内容,定期日期以及重复出现。

表格如下:

  • 活动
  • Events_Recurring

以下是事件表BIGGER PICTURE

的一部分

events table

这就是Events_Recurring表的样子

events recurring table

当客户端将其检查为重复发生时,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日,那就是这样。

2 个答案:

答案 0 :(得分:11)

一句忠告。

虽然从设计的角度来看,设计一个数据库来存储重复模式的“描述”是一种非常干净的方法,但你可能会遇到很多问题。

我前段时间做了一个类似方法的项目(我将查找数据库设计并将其添加到我的答案中),虽然我能够重现周期性事件的确切日期/时间,但是在以下情况下会遇到问题;大部分来自于:

重复发生的事件描述重复模式,因此实际(个别)事件不是数据库中的物理记录

  1. 如果客户决定添加新活动,您将如何检查它是否与任何现有活动重叠?您必须根据重复模式计算所有“事件”。
  2. 如果客户决定需要更改活动的预定时间,那么您将如何将此更改应用于所有未来事件,而不适用于过去发生的事件(您将必须复制原始事件,修改其结束日期,并使用新的开始日期设置重复事件)
  3. 如果客户决定他希望从重复模式中删除一天(例如,单个事件已被取消),您还必须将原始事件拆分为 two < / em>单独重复,有'已取消/已屏蔽'日期/时间表
  4. 如果人们需要为特定事件“预订”,您将无法将它们附加到“真实”事件记录中,因为个别事件因为它们实际上并不存在于数据库中。例如要检查单个事件是否可以重新调度或取消,您需要从代码执行此操作,因为数据库无法使用外键约束来自动更新相关的预留
  5. 关于表现;因为没有物理存储个别事件,所以每次要显示它们时都必须计算它们。考虑在数据库中有1000个重复发生的事件,并尝试在两年后显示第23周的“日历”。您必须分析所有重复事件模式并计算他们生成的所有事件!
  6. 当然,所有这些都取决于您系统的实际使用情况,但我想提醒您注意我们遇到的问题。

    这是'schedule'表的架构(包含定期事件模式);

    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中,您可能只想更新未来的事件,因此“重复发生的事件”仍然需要“拆分”为两个才能实现。在这种情况下,“未来”事件需要附加到新的“经常性事件”上,旧事件将依附于现有的“经常性事件”
    4. 在您的数据库/软件设计中投入时间,正确调查设计是否“适用于您正在尝试实现的目标”。测试它,尝试一些事情,如果它们不起作用,不要犹豫“扔掉它”,通常从头开始比尝试“修复”事情更容易。一个合适的设计需要花费时间,并且可能需要几次“重新设计”才能使其正确,但最终为您节省时间和金钱。

      希望这有帮助,祝你好运!

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

试试这个并告诉我它是否有效