skip to Main Content

I have a multi-dimensional array as shown below. I would like to display the data in a table, with each day of the week and its opening and closing times in one row. Expected result of the table is attached below.

I’m not familiar with arrays so I have not really tried anything worth mentioning here.

$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" => []
    ]
];
 

enter image description here

2

Answers


  1. You can do it like this. Please read the comments within the code, and the notes below the output.

    <?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;
    ?>
    

    The code above outputs (verbatim, empty lines and all):

        <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>
    

    Test it here.


    Notes

    I’ve repacked the initial array, to make it easier to loop through it and generate an HTML string to be rendered later on. The repacking could be avoided if you control the way how the initial table (the one I dubbed $times in the provided code) is formed.

    The rendered HTML table is a barebones table – you could provide CSS classes as you loop through it, or in the opening part of the $html variable which contains the thead and tbody.

    Also, if you need to style the non-empty (or empty) table cells, you could do that with CSS classes as well.

    The code has been adjusted to reflect on your comment – you can now provide N workslots during the day.

    Login or Signup to reply.
  2. In my opinion, there are far too many loops in @FiddlingAway’s answer. You need one preparatory loop to count the number of needed time slots for the week. Then you need a nest loop to traverse only the opening times data.

    As you traverse the opening times, access the related closing times by their shared day key and index. I’ll use a somewhat fancy technique to implode the time range strings using the spread operator and null coalescing so that an empty string is returned when there is no time data.

    Code: (Demo)

    $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>',
                implode(
                    ' to ',
                    [
                        ...(array) ($opens[$i] ?? []),
                        ...(array) ($times['closing_time'][$day][$i] ?? [])
                    ]
                )
            );
        }
        echo '</tr>';
    }
    echo '</table>';
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search