减少工作时间显示的代码长度


Reduce the code length of a work hours display

我编写了一些代码来从数据库中检索不同餐厅的不同工作时间,并显示它们现在是否开放。

工作时间定义如下:10:30to13:30/18:30to22:30 .

问题是我找不到一个简短的方法来编写下面所有的代码。我怎样才能缩短它的长度?

if ($result > 0) {
    while($row = $stmt->fetch()) {
        //SETUP HOURS FOR EACH DAY
        $timesSun = $row['sunday'];
        $timesMon = $row['monday'];
        $timesTue = $row['tuesday'];
        $timesWed = $row['wednesday'];
        $timesThu = $row['thursday'];
        $timesFri = $row['friday'];
        $timesSat = $row['saturday'];
        //SEPARATE DAY & NIGHT
        $sepDNsun = explode('/',$timesSun);
        $sepDNmon = explode('/',$timesMon);
        $sepDNtue = explode('/',$timesTue);
        $sepDNwed = explode('/',$timesWed);
        $sepDNthu = explode('/',$timesThu);
        $sepDNfri = explode('/',$timesFri);
        $sepDNsat = explode('/',$timesSat);
        //SEPARATE OPEN AND CLOSE
        $daySun = explode('to',$sepDNsun[0]);
        $nightSun = explode('to',$sepDNsun[1]);
        $dayMon = explode('to',$sepDNmon[0]);
        $nightMon = explode('to',$sepDNmon[1]);
        $dayTue = explode('to',$sepDNtue[0]);
        $nightTue = explode('to',$sepDNtue[1]);
        $dayWed = explode('to',$sepDNwed[0]);
        $nightWed = explode('to',$sepDNwed[1]);
        $dayThu = explode('to',$sepDNthu[0]);
        $nightThu = explode('to',$sepDNthu[1]);
        $dayFri = explode('to',$sepDNfri[0]);
        $nightFri = explode('to',$sepDNfri[1]);
        $daySat = explode('to',$sepDNsat[0]);
        $nightSat = explode('to',$sepDNsat[1]);
        //SET OPEN & CLOSE
        $dayOpenSun = $daySun[0];
        $dayCloseSun = $daySun[1];
        $nightOpenSun = $nightSun[0];
        $nightCloseSun = $nightSun[1];
        $dayOpenMon = $dayMon[0];
        $dayCloseMon = $dayMon[1];
        $nightOpenMon = $nightMon[0];
        $nightCloseMon = $nightMon[1];
        $dayOpenTue = $dayTue[0];
        $dayCloseTue = $dayTue[1];
        $nightOpenTue = $nightTue[0];
        $nightCloseTue = $nightTue[1];
        $dayOpenWed = $dayWed[0];
        $dayCloseWed = $dayWed[1];
        $nightOpenWed = $nightWed[0];
        $nightCloseWed = $nightWed[1];
        $dayOpenThu = $dayThu[0];
        $dayCloseThu = $dayThu[1];
        $nightOpenThu = $nightThu[0];
        $nightCloseThu = $nightThu[1];
        $dayOpenFri = $dayFri[0];
        $dayCloseFri = $dayFri[1];
        $nightOpenFri = $nightFri[0];
        $nightCloseFri = $nightFri[1];
        $dayOpenSat = $daySat[0];
        $dayCloseSat = $daySat[1];
        $nightOpenSat = $nightSat[0];
        $nightCloseSat = $nightSat[1];
        //SET STORE OPENING HOURS
        $storeSchedule = [
            'Sun' => [$dayOpenSun => $dayCloseSun, $nightOpenSun => $nightCloseSun],
            'Mon' => [$dayOpenMon => $dayCloseMon, $nightOpenMon => $nightCloseMon],
            'Tue' => [$dayOpenTue => $dayCloseTue, $nightOpenTue => $nightCloseTue],
            'Wed' => [$dayOpenWed => $dayCloseWed, $nightOpenWed => $nightCloseWed],
            'Thu' => [$dayOpenThu => $dayCloseThu, $nightOpenThu => $nightCloseThu],
            'Fri' => [$dayOpenFri => $dayCloseFri, $nightOpenFri => $nightCloseFri],
            'Sat' => [$dayOpenSat => $dayCloseSat, $nightOpenSat => $nightCloseSat]
        ];
        // current or user supplied UNIX timestamp
        $timestamp = time();
        // default status
        $status = $lang["NO-READY"];
        // get current time object
        $currentTime = (new DateTime())->setTimestamp($timestamp);
        // loop through time ranges for current day
        foreach ($storeSchedule[date('D', $timestamp)] as $startTime => $endTime) {
            // create time objects from start/end times
            $startTime = DateTime::createFromFormat('G:i', $startTime);
            $endTime   = DateTime::createFromFormat('G:i', $endTime);
            // check if current time is within a range
            if (($startTime < $currentTime) && ($currentTime < $endTime)) {
                $status = $lang["READY"];
                break;
            }
        }
        //OUTPUT CONTENT
        echo '<li>
                  <div class="rest-list-content">
                      <a href="'. $location .'/restaurants/'. $row["rest_url"] .'">
                      <img src="images/all_rest/'. $row["rest_logo"] .'" alt="'. $row["rest_name"] .'">
                      <h1>'. $row["rest_name"] .'</h1>
                      <p>Cuisine: <span>'. $row["cuisine_name"] .'</span></p>
                      <p>Minimun Order: <span>$'. $row["rest_min_order"] .'</span></p>
                      <p class="availability">'. $status .'</p>
                      </a>
                  </div>
              </li>';
    }
} else {
    echo "0 results";
}

引言

我可能错了,但是看看这段代码,似乎你正在做的是显示餐馆现在是否开业。

这里有很多需要优化的地方:

  • 您不断重新声明$timestamp = time();和与之相关的其他变量。这是相当低效的,因为在脚本执行期间时间不会改变太多。即使脚本运行时间超过一秒钟,这也可以忽略不计。必须在循环之前声明一次。
  • 你处理一周的所有7天,而你只需要与今天对应的一天,我们可以减少85%的工作量。
  • 这么多独特的变量。这可以大大减少。数组是我们的朋友。

让我们减少

$currentTime = new DateTime('now');
$currentDay  = strtolower($currentTime->format('l'));
if($result > 0) {
    while($row = $stmt->fetch()) {
        $schedule = explode('/',
            str_replace('to', '/', $row[$currentDay])
        );
        foreach($schedule as $time) {
            $schedule['time'][] = DateTime::createFromFormat('G:i', $time);
        }
        $status =
            ($schedule['time'][0] <= $currentTime && $currentTime <= $schedule['time'][1])
            ||
            ($schedule['time'][2] <= $currentTime && $currentTime <= $schedule['time'][3])
            ? $lang["READY"]
            : $lang["NO-READY"];
        /*
        HTML GOES HERE
        */
    }
}
else {
    echo '0 results';
}

发生了什么

由于日期和时间在脚本执行过程中不太可能改变,因此我们将这部分移到了开头。

  • 这返回一个DateTime对象为"现在",不需要调用time():

    $currentTime = new DateTime('now');
    
  • 返回今天的完整文本日期,将其转换为小写以匹配数据库记录(例如:tuesday):

    $currentDay  = strtolower($currentTime->format('l'));
    
  • 对于迭代的每条记录:

    • 我们使用$row[$currentDay],这是今天的数据。
    • 我们用/代替to,结果是xx:xx/xx:xx/xx:xx/xx:xx
    • 我们使用/爆炸。

      $schedule = explode('/',
          str_replace('to', '/', $row[$currentDay])
      );
      
    • 我们现在有一个包含4个值的数组:

      Array
      (
          [0] => 9:30
          [1] => 13:30
          [2] => 17:30
          [3] => 20:30
      )
      
    • 我们根据这些值分别创建一个DateTime对象,并将它们存储在同一个数组中:

      foreach($schedule as $time) {
          $schedule['time'][] = DateTime::createFromFormat('G:i', $time);
      }
      
    • 我们现在有了这个数组:

      Array
      (
          [0] => 9:30
          [1] => 13:30
          [2] => 17:30
          [3] => 20:30
          [time] => Array
              (
                  [0] => DateTime Object
                      (
                          [date] => 2015-09-29 09:30:00.000000
                          [timezone_type] => 3
                          [timezone] => Europe/Paris
                      )
                  [1] => DateTime Object
                      (
                          [date] => 2015-09-29 13:30:00.000000
                          [timezone_type] => 3
                          [timezone] => Europe/Paris
                      )
                  [2] => DateTime Object
                      (
                          [date] => 2015-09-29 17:30:00.000000
                          [timezone_type] => 3
                          [timezone] => Europe/Paris
                      )
                  [3] => DateTime Object
                      (
                          [date] => 2015-09-29 20:30:00.000000
                          [timezone_type] => 3
                          [timezone] => Europe/Paris
                      )
              )
      )
      
    • 我们使用一个三元操作符来设置状态(true ? true : false)。
      这检查"现在"是否同时在早晨或晚上时间之间。

      $status =
          ($schedule['time'][0] <= $currentTime && $currentTime <= $schedule['time'][1])
          ||
          ($schedule['time'][2] <= $currentTime && $currentTime <= $schedule['time'][3])
          ? $lang["READY"]
          : $lang["NO-READY"];
      
    • $status现在可用,html可以构建了

    • 重复,直到没有记录。

  • 退出循环

  • 做完了。