0

I want to merge the table row if the date have an same id's. I have some array data like this :

Array
(
    [0] => Array
        (
            [id] => 2
            [date] => 05/13/2014
            [content] => some contents 1
            [act] => act1 act2 act3
        )
    [1] => Array
        (
            [id] => 2
            [date] => 05/28/2014
            [content] => some contents 1
            [act] => act1 act2 act3
        )
    [2] => Array
        (
            [id] => 7
            [date] => 06/04/2014
            [content] => some contents 2
            [act] => act1 act2 act3
        )
)

Then I tried to group its data into the same id by :

            if($queryx = $this->mymodel->myfunction($par)){
                $datax = $queryx;
            }           
            $i = 0;
            foreach ($datax  as $idx => $val) {
                $dates[$val['id']][$i] = $val['date'].",".$val['id'];
                $contn[$val['id']][$i] = $val['content'];

                $i++;
            }

then :

            $j = 0; $y = 0;
            echo "<table border='1'>\r\n";
            foreach ($dates as $idx => $val) {
                $tmpexp = explode(',', $val[$j]);
                echo "<tr>\r\n";
                echo "<td rowspan='".count($val)."'>".$tmpexp[0]."</td>\r\n";
                foreach ($val as $idx1 => $val1) {
                    if($idx1 > 0)
                    {
                        echo "<tr>\r\n";
                    }
                    echo "<td>".$dates[$tmpexp[1]][$y]."</td>\r\n";
                    if($idx1 < 1)
                    {
                        echo "<td rowspan='".count($val)."'>".$contn[$tmpexp[1]][$y]."</td>\r\n";                       
                        echo "<td rowspan='".count($val)."'>act1 act2 act3</td>";
                        echo "</tr>\r\n";
                    }
                    $y++;
                }
                $j++;   
            }
            echo "</table>";

There is no problem if the data have at least two child, but if the date only have one child (see data with id's 7) there is show an error because Undefined offset. So how I add some handler if there is only one child on the data. There is my desired result:

Please see this image:

4
  • please explain why 5/28 has no content nor act? Commented Jun 4, 2014 at 5:18
  • 1
    because the content has rowspan = 2. remember that 5/13 adn 5/28 has the same id Commented Jun 4, 2014 at 5:20
  • I see, so you want to skip content and act when the current id = last id? why can't you just compare it like that while iterating? Commented Jun 4, 2014 at 5:26
  • Added 'rowspan' for vertical formatting. Commented Jun 4, 2014 at 14:42

2 Answers 2

2

I use the 'read ahead' technique for processing nested loops. It does mean that 'foreach' loops cannot be used as the next record must be read as soon as the current one has been processed. Basically, the last action you do in the loop is read the next record as you are setting it up for the next iteration. Note, you never test when to print a record as that is decided by the structure of the groups. The code loops are the same as the structure of the groups in the data

A 'group' is all the records with the same id.

I assume that the 'content' and 'act' are identical for each entry in the group.

Edited to add 'rowspan' attributes to the appropriate 'td' tags. I suspect css may be easier at this point.

The issue is that the group cannot be displayed until it is known how many entries are in it.

So, i 'buffer' all the records belonging to a group in an array. at the end of the group, it is displayed with the appropriate 'rowspan' attributes in the html.

It is tested on PHP 5.3.18. It includes test data.

<?php /* Q24028866 */
$testData = array(array('id' => 2, 'date' => '05/13/2014', 'content' => 'some contents 2', 'act' => 'act1 act2 act3'),
                  array('id' => 2, 'date' => '05/28/2014', 'content' => 'some contents 2',  'act' => 'act1 act2 act3'),
                  array('id' => 7, 'date' => '06/04/2014', 'content' => 'some contents 7',  'act' => 'act1 act2 act3'),
                  array('id' => 8, 'date' => '06/08/2014', 'content' => 'some contents 8',  'act' => 'act1 act2 act3'),
                  array('id' => 8, 'date' => '06/09/2014', 'content' => 'some contents 8',  'act' => 'act1 act2 act3'));
?>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<table border='1'>
<thead><th>Date</th><th>Content</th><th>Act</th></thead>
<?php
// use 'read ahead' so there is always a 'previous' record to compare against...
$iterContents = new \ArrayIterator($testData);
$curEntry = $iterContents->current();

while ($iterContents->valid()) { // there are entries to process

    $curId = $curEntry['id'];

    // buffer the group to find out how many entries it has...
    $buffer = array();
    $buffer[] = $curEntry;

    $iterContents->next(); // next entry - may be same or different id...
    $curEntry = $iterContents->current();

    while ($iterContents->valid() && $curEntry['id'] == $curId) {  // process the group...
        $buffer[] = $curEntry; // store all records for a group in the buffer

        $iterContents->next(); // next entry - may be same or different id...
        $curEntry = $iterContents->current();
    }

     // display the current group in the buffer...
     echo '<tr>';
     echo '<td>', $buffer[0]['date'], '</td>';
     $rowspan = count($buffer) > 1 ? ' rowspan="'. count($buffer) .'"' : '';
     echo '<td', $rowspan, '>', $buffer[0]['content'], '</td>',
           '<td', $rowspan, '>', $buffer[0]['act'], '</td>';
     echo '</tr>';
     for($i = 1; $i < count($buffer); $i++) {
          echo '<tr><td>', $buffer[$i]['date'], '</td>';
          echo '</tr>';
     }
} ?>
</table>
</body>
</html>
Sign up to request clarification or add additional context in comments.

2 Comments

Hi @Ryan Vincent, thanks for your work. may be there is an misunderstanding. please take a look on my update picture above. I mean there is an rowspan if the data have the same id. so, if the data have the same id --> rows span for id, content dan act, but not for dates, because date always different... any idea for this... thanks...
it work perfectly! so many thanks to you @Ryan Vincent... great..!!
1

The following code will give you a clue what you should do,

$newArray = array();        
$counter=0;        
foreach($datax  as $key=>$val){        
    $newArray[$val['id']][$counter]['date'] = $val['date'];       
    $newArray[$val['id']][$counter]['content'] = $val['content'];        
    $newArray[$val['id']][$counter]['act'] = $val['act'];        
    $counter++;        
}        
$newArray = array_map('array_values', $newArray);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.