У меня есть многомерный массив, как показано ниже. Я хотел бы отобразить данные в таблице, где каждый день недели и время его открытия и закрытия будут в одной строке. Ожидаемый результат таблицы прилагается ниже.
Я не знаком с массивами, поэтому не пробовал ничего, о чем стоит упомянуть здесь.
$times = [
"opening_time" => [
"monday" => ["10:30 am", "6:30 pm"],
"tuesday" => ["12:30 pm"],
"wednesday" => ["4:30 pm"],
"thursday" => ["2:30 pm"],
"friday" => ["4:00 pm"],
"saturday" => ["6:00 am"],
"sunday" => []
],
"closing_time" => [
"monday" => ["6:00 pm", "10:30 pm"],
"tuesday" => ["7:00 pm"],
"wednesday" => ["10:00 pm"],
"thursday" => ["6:30 pm"],
"friday" => ["11:00 pm"],
"saturday" => ["6:00 pm"],
"sunday" => []
]
];
@FiddlingAway временных интервалов может быть более двух, поэтому мне нужно решение, которое распечатывало бы все интервалы.
@FiddlingAway Под слотом я подразумеваю пару часов открытия и закрытия (например, с 10:00 до 18:00). В предоставленном массиве понедельник будет иметь 2 временных интервала, воскресенье — 0, а остальные дни — по 1.
Я скорректировал код в соответствии с вашими требованиями. Взгляни, пожалуйста.
Если можно, то ответ @mickmackusa лучше, чем тот, который я предложил. Вы бы вместо этого были против того, чтобы принять это как ответ?
@FiddlingAway Вместо этого я принял ответ mickmackusa. Спасибо всем!
Вы можете сделать это вот так. Пожалуйста, прочитайте комментарии внутри кода и примечания под выводом.
<?php
function renderSlots($columns,$repacked,$day,$time) {
$html = '';
for($i = 0; $i < $columns; $i++) {
// Check if slot i is set
if (isset($time[0][$i])) {
$html .= '
<td>'.$time[0][$i].' to '.$repacked[$day]["closing_time"][0][$i].'</td>
';
} else {
$html .= '
<td></td>
';
}
}
return $html;
}
$times = [
"opening_time" =>[
"monday" => [
0 => "10:00 am",
1 => "6:30 pm",
2 => "some other time"
],
"tuesday" => [
0 => "12:30 pm"
],
"wednesday" => [
0 => "4:30 pm"
],
"thursday" => [
0 => "2:30 pm"
],
"friday" => [
0 => "4:00 pm"
],
"saturday" => [
0 => "6:00 am"
],
"sunday" => []
],
"closing_time" => [
"monday" => [
0 => "6:00 pm",
1 => "10:30 pm",
2 => "some other closing time"
],
"tuesday" => [
0 => "7:00 pm"
],
"wednesday" => [
0 => "10:00 pm"
],
"thursday" => [
0 => "6:30 pm"
],
"friday" => [
0 => "11:00 pm"
],
"saturday" => [
0 => "6:00 pm"
],
"sunday" => []
]
];
// Repacking your original array to be like this
/*
$arr = [
day => [
opening_time => [
10:00 am
6:30 pm
],
closing_time => [
6:00 pm
10:30 pm
]
]
...
];
*/
$repacked = [];
// This is to determine the number of columns we'll need
// Letters a-g are variables, standing in for the number of
// slots in a day
/*
$arr = [
"monday" => a,
"tuesday" => b,
"wednesday" => c,
"thursday" => d,
"friday" => e,
"saturday" => f,
"sunday" => g
];
*/
$daySlots = [];
foreach($times as $type=>$days) {
foreach($days as $day=>$time) {
if (!isset($repacked[$day][$type])) {
$repacked[$day][$type] = [];
}
$repacked[$day][$type][] = $time;
if (!isset($daySlots[$day])) {
$daySlots[$day] = 0;
}
$daySlots[$day] = count($time);
}
}
// Get the max number of work slots
$columns = max($daySlots);
$html = '
<table>
<thead>
<tr>
<th>Day</th>
';
// As many columns as there are slots
for($i = 1; $i <= $columns; $i++) {
$html .= '
<th>Working hours '.$i.'</th>
';
}
$html .= '
</tr>
</thead>
<tbody>
';
// Loop through days...
foreach($repacked as $day=>$times) {
$html .= '
<tr>
<td>'.ucfirst($day).'</td>
';
// ... then through specific opening times
foreach($times as $type=>$time) {
// We've already picked this up during one of
// the previous loop passes, we don't need it now
if ($type === "closing_time") {
continue;
}
// Skip days with no set time - generate $columns number of cells
if (!$time[0]) {
$html .= str_repeat('<td></td>'.PHP_EOL,$columns);
continue;
}
// With the outline of the repacked array given in
// lines 72-81, $time[0][0] is, in the first run through
// the loop:
/*
$repacked
$day (e.g. Monday)
$type (e.g. opening_time)
$time (a nested array, e.g. [ [10:00 am, 6:30 pm] ])
$time[0] ( first element of the nested array, e.g. [10:00 am, 6:30 pm] )
$time[0][1] (first time, e.g. 10:00 am)
*/
// Check the slots, and generate columns
$html .= renderSlots($columns,$repacked,$day,$time);
}
$html .= '
</tr>
';
}
$html .= '
</tbody>
</table>
';
echo $html;
?>
Код выше выводит (дословно, пустые строки и все такое):
<table>
<thead>
<tr>
<th>Day</th>
<th>Working hours 1</th>
<th>Working hours 2</th>
<th>Working hours 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>Monday</td>
<td>10:00 am to 6:00 pm</td>
<td>6:30 pm to 10:30 pm</td>
<td>some other time to some other closing time</td>
</tr>
<tr>
<td>Tuesday</td>
<td>12:30 pm to 7:00 pm</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Wednesday</td>
<td>4:30 pm to 10:00 pm</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Thursday</td>
<td>2:30 pm to 6:30 pm</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Friday</td>
<td>4:00 pm to 11:00 pm</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Saturday</td>
<td>6:00 am to 6:00 pm</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Sunday</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Проверьте это здесь.
Примечания
Я переупаковал исходный массив, чтобы его было проще обработать и сгенерировать строку HTML для последующей обработки. Перепаковки можно было бы избежать, если бы вы контролировали способ формирования исходной таблицы (той, которую я назвал $times
в предоставленном коде).
Отрисованная HTML-таблица представляет собой базовую таблицу: вы можете предоставлять классы CSS по мере ее прохождения или в открывающей части переменной $html
, которая содержит thead
и tbody
.
Кроме того, если вам нужно стилизовать непустые (или пустые) ячейки таблицы, вы также можете сделать это с помощью классов CSS.
Код был скорректирован с учетом вашего комментария: теперь вы можете предоставить N рабочих слотов в течение дня.
На мой взгляд, в ответе @FiddlingAway слишком много циклов. Вам понадобится один подготовительный цикл, чтобы подсчитать количество необходимых временных интервалов на неделю. Затем вам понадобится вложенный цикл для обхода только данных о времени открытия.
Просматривая время открытия, получайте доступ к соответствующему времени закрытия по их общему ключу дня и индексу.
Код: (Демо)
$slots = max(array_map('count', $times['opening_time']));
echo '<table>';
foreach ($times['opening_time'] as $day => $opens) {
echo "<tr><td>$day</td>";
for ($i = 0; $i < $slots; ++$i) {
printf(
'<td>%s</td>',
isset($opens[$i], $times['closing_time'][$day][$i])
? "{$opens[$i]} to {$times['closing_time'][$day][$i]}"
: ''
);
}
echo '</tr>';
}
echo '</table>';
Всегда ли у вас будет такая схема (двухчастный рабочий день) или бывают случаи, когда у вас их больше двух или только одна?