Skip to content
Advertisement

PHP array break if the column exceeds specific number [closed]

Hello i tried modifying a code left by the dev i hired in 2018 but not being a coder is really taking a toll on me. What do i want to do here is have this code create another table if the first table loop have more than 3 cities and repeat the process to create tables instead of adding new columns in the existing table, the tables by default have raows equal to days in month but the columns are fethced from database as locations. here is the code.

if (!empty($locations)) {
    echo "<table class='table table-striped tbl tbl-result text-center top1'>rnt<thead>rntt<tr>rnttt<th>";
    echo lang("label_date");
    echo "</th>rnttt";
    foreach ($locations as $location) {
        echo "ttt<th>";
        echo $location->name;
        echo "</th>rnttt";
    }
    echo "tt</tr>rnt</thead>rnt<tbody>rnt";
    foreach ($dates as $date) {
        echo "trnt<tr>rntt<td>";
        echo $date;
        echo "</td>rntt";
        foreach ($locations as $location) {
            echo "ttt";
            $data = $this->sales_model->result_row($date, $location->id, $sales);
            echo "ttt";
            if ($data) {
                echo "ttt<td>";
                echo $this->sales_model->append_zero($data);
                echo "</td>rnttt";
            } else {
                echo "ttt<td></td>rnttt";
            }
            echo "tt";
        }
        echo "t</tr>rnt";
    }
    echo "t</tbody>rn</table>rn";
}

I tried if else statements and continue break but to no avail i don’t even know what i am doing at this point. What it displays is below and i want it to break 3 cities in each loop image

Advertisement

Answer

Your question is a little vague. But if I understand you correctly, you want to limit the number of sales per city to the first three columns (city1, city2, city3) for every date. While keeping all the city headers in tact.

foreach might not be the best construct to do this, but seeing as you are out of your depth as it is, I will suggest something close to what you already have.

Try replacing the second occurrence of foreach ($locations as $location) { with:

foreach ($locations as $locationIndex => $location) {
    if ($locationIndex > 2)
        break;

This assumes that $locations is a simple array with a sequential numeric index. If this is not exactly what you’re trying to do, then please elaborate so I can provide a more accurate answer.

UPDATE

See this eval for a live demo of one possible approach. I used heredoc syntax for the building the HTML because it’s a little easier to read for the purpose of this example. Here’s the code. You can set $numColumns to control the number of table columns.

<?php

// Mock function to generate some random sales data, sometimes returning nothing.
function getLocationSalesForDate(DateTime $date, string $location)
{
    // Your business logic goes here.
    // Get the date as a string using DateTime::format().
    
    // Return a random mock value for this demo. Will randomly return NULL so as to simulate
    // your table view.
    return (mt_rand(0, 3) === 1)?NULL:mt_rand(15, 70);
}

$locations = ['city 1', 'city 2', 'city 3', 'city 4', 'city 5', 'city 6'];
$numColumns = 3;

$dateStart = new DateTime;
// 'P7D' means a period ('P') of 7 ('7') days ('D') from $dateStart. Consult the documentation of DateInterval's constructor for details.
$dateEnd = (clone $dateStart)->add(new DateInterval('P7D'));

// Segment your locations to however many you want to show on a single line.
foreach (array_chunk($locations, $numColumns) as $columnHeadings)
{
    // Output table heading for this group of locations.
    $html = <<<EOT
<table>
    <thead>
        <tr>
            <th>Date</th>

EOT;

    // Write out each location as a column heading.
    foreach ($columnHeadings as $columnHeading)
        $html .= <<<EOT
            <th>$columnHeading</th>

EOT;

    $html .= <<<EOT
        </tr>
    </thead>

EOT;

    // Output sales per day for this location.
    $html .= <<<EOT
    <tbody>

EOT;

    // Loop through each day between $dateStart and $dateEnd.
    $dateIterator = clone $dateStart;
    while ($dateIterator != $dateEnd)
    {
        // Start new row, print date on first column.
        $html .= <<<EOT
        <tr>
            <td>{$dateIterator->format('Y-m-d')}</td>

EOT;

        // Loop through this segment's locations and fetch sales for this day.
        foreach ($columnHeadings as $location)
        {
            // Retrieve mock sales data for this day on this location.
            $sales = getLocationSalesForDate($dateIterator, $location);
            
            // Record sales if we have any.
            if ($sales)
                // Have sales.
                $html .= <<<EOT
            <td>$sales</td>

EOT;
                else
                    // No sales for this day.
                    $html .= <<<EOT
            <td><!-- Empty cell if no sales recorded for this location on this day. --></td>

EOT;
        }
        
        // Close sales data row.
        $html .= <<<EOT
        </tr>

EOT;

        // Advance to next day for this location.
        $dateIterator->add(new DateInterval('P1D'));
    }
    
    // Close table for this location group.
    $html .= <<<EOT
    </tbody>
</table>

EOT;

    // Output table to user.
    echo $html;
}
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement