3

だから私は配達時間のためのフィールドをデータベースに持っています、そしてそれは特定のフォーマットです(確かに私のデザインではありません!):ここにいくつかの例があります:

M、T、W、TH; MTWTH 9〜4クローズ12〜1

T、W、TH、F; TTHF 9〜5クローズ12〜2、W 9〜12

T、W、TH、F; T 10〜7クローズ2〜3、WTH 9〜6クローズ1〜2、F 8〜5クローズ1〜2

つまり、基本的には、コンマで区切られ、その後にセミコロンが続く日のリストがあります。セミコロンの後には、分割されていない日のリストがあり、その後に休憩時間を含む配達時間が続きます。問題は、配達時間が毎日異なる、すべての日で同じ、またはたとえば月曜日と火曜日で同じ、次に水曜日で異なる、木曜日と金曜日で同じである可能性があることです(ただし、木曜日と金曜日は月曜日と金曜日とは配達時間が異なります火曜日)。また、配達時間が数日間一致する場合は、それらの日をグループ化して、グループの日の後に配達時間をリストし、その後に他の一致する日または1日をリストする必要があります。配達時間が指定されている最初の日が最初に行く必要があります。

私は知っている、フォーマットはばかげているし、配達日/時間は組織IDによってリンクされた別のテーブルにあるべきです、しかしそれは彼らがいくつかのダウンロードファイルのために現在使用しているフォーマットです。後で変更したいのですが、今のところ... 4つのドロップダウン(From、To、Closed From、Closed To)からの入力をその形式に変換する方法がわかりません。いずれの日も閉店時間がまったくない場合があります。少なくとも1日は配達時間を指定する必要があります(私はそれをチェックします)。

もちろん、最初の部分(セミコロンの前)を取得しました。これは簡単ですが、その後は完全に行き詰まります。配達のある日がすべて同じ時間であれば、問題はありません。しかし、それは日々まったく異なる可能性があるので、私はそれを行う方法がわかりません。

これがこれまでの処理ブロックです。

$ triggeredは、トリミングされたPOST値の配列です。

$trimmed ['1Monday']はMondayFrom、$ Trimmed ['2Monday']はMondayTo、

$trimmed['3Monday']は月曜日の休業日です。$trimmed['4Monday']は月曜日の休業日です。

したがって、$M_times変数には月曜日の開始/終了時間があります。

$ days_del配列は、必要な形式の最初の部分である文字列を後で作成するために使用されます。

いくつかの時間を指定して最初の日を取得し、その後の一致をキャッチすることを試みることができますが、最初の配信日が他の日と異なる値を持っている場合は役に立ちませんが、その後にいくつかの一致する値があります。別の(番号付きの)日配列を使用する必要があるかどうかさえわかりません。または、キーにMFを使用するメイン配列だけで使用できます。

<?php

$days = array('M' => 'Monday', 'T' => 'Tuesday', 'W' => 'Wednesday', 'TH' => 'Thursday', 'F' => 'Friday');

$days_numbered = array(1 => 'M', 'T', 'W', 'TH', 'F');

$days_del = $matches = $full_list = array();

$days_delivery2 = '';

$count_no_del = 0;  # initialize count for days with no delivery
$times_6 = '';



foreach ($days as $k => $v){  #####  Beginning of days loop


if (isset($trimmed["1$v"]) &&  isset($trimmed["2$v"])){ #  If both closing and opening times have been specified

$days_del[] = $k;
${$k.'_times'} = $trimmed["1$v"] . ' TO ' . $trimmed["2$v"];

if ((!isset($trimmed["3$v"]) && isset($trimmed["4$v"])) || (isset($trimmed["3$v"]) && !isset($trimmed["4$v"]))){  #  If only beginning or only end of lunch(?) break has been specified

$errors[] = 'Delivery times for $v - please specify both start and end of closing time.';

}elseif (isset($trimmed["3$v"]) && isset($trimmed["4$v"]){  #  If both beginning and end of lunch(?) breakh have been specified

${$k.'_times'} .= 'CLOSED' .  $trimmed["3$v"] . ' TO ' . $trimmed["4$v"];
}

    }elseif ((!isset($trimmed["1$v"]) &&  isset($trimmed["2$v"])) || (isset($trimmed["1$v"]) &&  !isset($trimmed["2$v"]))){  #  If only closing or only  opening time has been specified

$errors[] = 'Delivery times for $v - please specify both start and end of delivery time.';
${$k.'_times'} = NULL;

    }elseif (!isset($trimmed["1$v"]) &&  !isset($trimmed["2$v"])){  # No delivery times specified for this day

${$k.'_times'} = NULL;
$count_no_del++;

    }

$full_list["$k"] = ${$k.'_times'};

}  #####  End of days loop



if ($count_no_del > 0){  #  If there are no delivery days specified
$errors[] = 'You must specify delivery hours for at least one day of the week.';
}

$days_delivery1 = implode(',', $days_del);
$days_delivery1 = $days_delivery1 . ' ; ';



foreach ($days_numbered as $num => $val){  #  Getting first day for which delivery hours have been specified
if (isset(${$val.'_times'}) && (${$val.'_times'} != NULL)){
${'times_'.$num} = ${$val.'_times'};
$first_day = $num;
break;
}
}




$check_array = array_keys($full_list, ${'times_'.$first_day}));  #  checking how many other days match the delivery hours for the first specified day.

foreach ($check_array as $array_key){
$days_delivery2 .= $array_key;
}

$days_delivery2 .= " " . ${'times_'.$first_day};


$note_line = $days_delivery1 . " "  ; #  second part, something like 'MTH 9 To 5, TW 10 TO 5 CLOSED 1 TO 2, F 10 TO 2' should go a s the second part of the string.
?>

ご覧のとおり、文字列の最初の部分をその形式($ days_delivery1)で取得した後、私は立ち往生していて、何をしているのかわかりません。私は2つの異なる配列(メインの配列と番号の付いた配列)を使用し、array_keysを使用して一致する値を見つけるという大胆な考えを持っていますが、それに取り組むときはいつでも壁にぶつかります。どんなアイデアでも大いに評価されるでしょう。

4

1 に答える 1

3

ここで潜在的に難しいのは、2番目のセクションのエントリのようにグループ化することです。これを克服するために、時間を4桁の表現に変換して正規化し、パターンを連結することをお勧めします。そのため、パターンごとに「署名」を作成します。

$_POST以下の例では、次の配列が対応する結果文字列になるという原則に取り組んでいます。

 $_POST1 = array(
   '1Monday' => 9,
   '2Monday' => 5,
   '3Monday' => 12,
   '4Monday' => 1,
   '1Tuesday' => 9,
   '2Tuesday' => 5,
   '3Tuesday' => 12,
   '4Tuesday' => 1,
   '1Wednesday' => 9,
   '2Wednesday' => 5,
   '3Wednesday' => 12,
   '4Wednesday' => 1,
   '1Thursday' => 9,
   '2Thursday' => 5,
   '3Thursday' => 12,
   '4Thursday' => 1,
   '1Friday' => 9,
   '2Friday' => 4,
   '3Friday' => 11,
   '4Friday' => 12
 );
 $result1 = "M, T, W, TH, F ; MTWTH 9 TO 5 CLOSED 12 TO 1, F 9 TO 4 CLOSED 11 TO 12";     

 $_POST2 = array(
   '1Monday' => '',
   '2Monday' => '',
   '3Monday' => '',
   '4Monday' => '',
   '1Tuesday' => 9,
   '2Tuesday' => 5,
   '3Tuesday' => 12,
   '4Tuesday' => 1,
   '1Wednesday' => 9,
   '2Wednesday' => 5,
   '3Wednesday' => 12,
   '4Wednesday' => 1,
   '1Thursday' => 9,
   '2Thursday' => 5,
   '3Thursday' => 12,
   '4Thursday' => 1,
   '1Friday' => 9,
   '2Friday' => 5,
   '3Friday' => 12,
   '4Friday' => 1
 );
 $result2 = "T, W, TH, F ; TWTHF 9 TO 5 CLOSED 12 TO 1";

次に、そのデータをどのように処理するかを見てみましょう。未処理のPOST配列を直接操作していると仮定します。

<?php

  // Obviously we will need this map if the inputs use the full day names
  $days = array('M' => 'Monday', 'T' => 'Tuesday', 'W' => 'Wednesday', 'TH' => 'Thursday', 'F' => 'Friday');

  // A couple of arrays to hold the results of the loop iterations
  $resultDays = $resultTimes = array();

  // First we iterate over the days
  foreach ($days as $dayCode => $dayFull) {

    // Data about this day
    $dayData = array(
      'open' => 0,
      'close' => 0,
      'lunchClose' => 0,
      'lunchOpen' => 0,
      'days' => array()
    );

    // First get the open/close times
    $open = $_POST["1$dayFull"];
    $close = $_POST["2$dayFull"];
    if (empty($open) || empty($close)) {
      // If we don't have both open/close times, skip this day
      continue;
    }

    // We definitely open on this day
    $resultDays[] = $dayCode;
    $dayData['open'] = $open;
    $dayData['close'] = $close;

    // Pad the strings to make the signature
    $openPadded = str_pad($open, 2, "0", STR_PAD_LEFT);
    $closePadded = str_pad($close, 2, "0", STR_PAD_LEFT);

    // Now look at lunch times
    $lunchClose = $_POST["3$dayFull"];
    $lunchOpen = $_POST["4$dayFull"];
    if (!empty($lunchClose) || !empty($lunchOpen)) {
      // If we have both open/close times, add a lunch break

      // Add data to $dayData
      $dayData['lunchClose'] = $lunchClose;
      $dayData['lunchOpen'] = $lunchOpen;

      // Pad the strings to make the signature
      $lunchClosePadded = str_pad($lunchClose, 2, "0", STR_PAD_LEFT);
      $lunchOpenPadded = str_pad($lunchOpen, 2, "0", STR_PAD_LEFT);

    } else {
      // So we don't break this signature
      $lunchClosePadded = $lunchOpenPadded = '';
    }

    // Build the signature
    $signature = $openPadded.$closePadded.$lunchClosePadded.$lunchOpenPadded;

    // Add day data to result times array
    if (!isset($resultTimes[$signature])) {
      $resultTimes[$signature] = $dayData;
    }
    $resultTimes[$signature]['days'][] = $dayCode;

  }

  // Now we can build the string

  // Like you say, first part is easy
  $firstPart = implode(', ', $resultDays);

  // Loop $resultTimes and construct to more sensible arrangements
  $secondPart = array();
  foreach ($resultTimes as $block) {
    $str = implode('', $block['days'])." {$block['open']} TO {$block['close']}";
    if (!empty($block['lunchClose']) && !empty($block['lunchOpen'])) {
      $str .= " CLOSED {$block['lunchClose']} TO {$block['lunchOpen']}";
    }
    $secondPart[] = $str;
  }

  // Now we can construct the final string
  $finalResult = $firstPart." ; ".implode(', ', $secondPart);

それが機能しているのを見てください

まあ、それは楽しかったです。

于 2012-07-12T20:27:25.047 に答える