嵌套的FOREACH语句不能按预期工作

嵌套的FOREACH语句不能按预期工作

问题描述:

In the first foreach statement, I have 4 attendeeid's in the attendees table.

In the second foreach, I have 1 attendeeid in the attend_date_temp table.

I'm trying to load a select box with names from the attendees table, less the one in the attend_date_temp table.

I thought that, since the first foreach would loop 4 times, the second foreach would also loop 4 times. But it doesn't. It loops one time, causing the code in the second foreach to not execute and load the select box with names.

How can this be written so that the second foreach loops 4 times like the first foreach so the select box will have the names loaded to it?

// Load Button Clicked
if(isset($_POST['loadnames'])) {

    /* Read the history file and get the last record for each attendee for a particular group 
    and a particular member and write them to the attend_date_temp table if attend_date = CURDATE().*/
    $stmt = $db->prepare('SELECT historyid, attend_date, attendeeid, groupid, memberid
                            FROM history 
                            WHERE groupid = :groupid
                            AND memberid = :memberid
                            AND attend_date = CURDATE()
                            ORDER BY historyid
                            DESC LIMIT 1');
    $stmt->bindValue(':groupid', $_POST['groupid'], PDO::PARAM_INT);
    $stmt->bindValue(':memberid', $_SESSION['memberid'], PDO::PARAM_INT);
    $stmt->execute();
    $result = $stmt->fetchAll();
    foreach($result as $row) {
        $aid = $row[2]; // set the attendeeid
        $stmt = $db->prepare('INSERT INTO attend_date_temp (attendeeid, groupid, memberid)
                                VALUES(:aid, :gid, :mid)');
        $stmt->bindValue(':aid', $aid, PDO::PARAM_INT);
        $stmt->bindValue(':gid', $_POST['groupid'], PDO::PARAM_INT);
        $stmt->bindValue(':mid', $_SESSION['memberid'], PDO::PARAM_INT);
        $stmt->execute();
    }   

    $aaa = 0; // used to set the first select box entry to "Select"
    /* Load the Select Box with names, less the ones found in attend_date_temp Table. */
    $stmt = $db->prepare('SELECT a.attendeeid, fname, lname, a.groupid, a.memberid, s.attendeeid, suspend
                            FROM attendees AS a
                            JOIN suspended AS s ON a.attendeeid = s.attendeeid 
                            WHERE a.memberid = :memberid
                            AND suspend = "N"
                            AND a.groupid = :groupid
                            ORDER BY lname');
    $stmt->bindValue(':memberid', $_SESSION["memberid"], PDO::PARAM_INT);
    $stmt->bindValue(':groupid', $_POST['groupid'], PDO::PARAM_INT);
    $stmt->execute();
    $result = $stmt->fetchAll();
    foreach($result as $row){
        echo '<script type="text/javascript">alert("In the first loop"); </script>';

        $aid = $row[0];
        $lname = $row[2];
        $fname = $row[1];
        $stmt = $db->prepare('SELECT attendeeid, memberid
                                FROM attend_date_temp
                                WHERE groupid = :groupid
                                AND attendeeid = :aid');
        $stmt->bindValue(':groupid', $_POST['groupid'], PDO::PARAM_INT);
        $stmt->bindValue(':aid', $aid, PDO::PARAM_INT);
        $stmt->execute();
        $result2 = $stmt->fetchAll();
        foreach ($result2 as $row2) { 
            echo '<script type="text/javascript">alert("In the second loop"); </script>';

            // evaluate attendees attendeeid against attend_date_temp attendeeid
            if($row2['attendeeid'] != $aid){    

                // Load the flush Table with the IDs from the selected group
                if($_SESSION['flush'] == 0) {
                    $stmt = $db->prepare('INSERT INTO flush (attendeeid, memberid)
                                                    VALUES(:attendeeid, :memberid)');
                    $stmt->bindValue(':attendeeid', $aid, PDO::PARAM_INT);
                    $stmt->bindValue(':memberid', $_SESSION['memberid'], PDO::PARAM_INT);
                    $stmt->execute();
                } 
                if($aaa == 0) {
                    echo "<option value='Select'>Select</option>";
                    echo "<option value=".$aid.">".$lname.", ". $fname."</option>"; 
                    $aaa = 1;
                } else { 
                    echo "<option value=".$aid.">".$lname.", ". $fname."</option>"; 
                }  
            }  
        }  
    } 
    $_SESSION['flush'] = 1;
    exit();
} // last brace: loadnames

The attend_date_temp table:

DROP TABLE IF EXISTS `attend_date_temp`;
CREATE TABLE `attend_date_temp` (
`attendeeid` int(10) unsigned NOT NULL,
`groupid` int(10) unsigned NOT NULL,
`memberid` int(10) unsigned NOT NULL,
KEY `attendeeid` (`attendeeid`),
KEY `memberid` (`memberid`),
CONSTRAINT `attend_date_temp_ibfk_1` FOREIGN KEY (`attendeeid`)  REFERENCES `attendees` (`attendeeid`) ON DELETE CASCADE,
CONSTRAINT `attend_date_temp_ibfk_2` FOREIGN KEY (`memberid`)   REFERENCES `members` (`memberid`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

The history table:

DROP TABLE IF EXISTS `history`;
CREATE TABLE `history` (
`historyid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`amount` float NOT NULL,
`subsidy` char(1) NOT NULL,
`last_payment` date NOT NULL,
`amount_paid` float NOT NULL,
`balance` float NOT NULL,
`attend` char(1) NOT NULL DEFAULT 'N',
`attend_date` date NOT NULL,
`groupid` char(1) NOT NULL,
`attendeeid` int(10) unsigned NOT NULL,
`memberid` int(10) unsigned NOT NULL,
PRIMARY KEY (`historyid`),
KEY `attendeeid` (`attendeeid`),
CONSTRAINT `history_ibfk_15` FOREIGN KEY (`attendeeid`) REFERENCES `attendees` (`attendeeid`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

UPDATE: This is a small part of a payment posting page. Names are loaded in the select box based on the group selected, then payments are posted by the name selected. This not only posts their payments but also their attendance. Once all the money has been collected, the remaining names not selected are marked as absent.

However, there are group members that attend groups that are not their own. When they make a payment, their money is posted and attendance recorded. BUT, and that's what this is all about, when that same person's group gets selected for payments, I don't want that person's name to get loaded. He's already paid, and his attendance has already been updated. To have him load again and be processed wld corrupt the history table. So I have to keep from double loading the same person. That's why I'm trying to use this attend_date_temp table.

Simple fix, use different variable names for the inner and outer loops:-

/* Load the Select Box with names, less the ones found in attend_date_temp Table. */
    $stmt = $db->prepare('SELECT a.attendeeid, fname, lname, a.groupid, a.memberid, s.attendeeid, suspend
                            FROM attendees AS a
                            JOIN suspended AS s ON a.attendeeid = s.attendeeid 
                            WHERE a.memberid = :memberid
                            AND suspend = "N"
                            AND a.groupid = :groupid
                            ORDER BY lname');
    $stmt->bindValue(':memberid', $_SESSION["memberid"], PDO::PARAM_INT);
    $stmt->bindValue(':groupid', $_POST['groupid'], PDO::PARAM_INT);
    $stmt->execute();
    $result = $stmt->fetchAll();
    foreach($result as $row){
        echo '<script type="text/javascript">alert("In the first loop"); </script>';

        $aid = $row[0];
        $lname = $row[2];
        $fname = $row[1];
        $stmt = $db->prepare('SELECT attendeeid, memberid
                                FROM attend_date_temp
                                WHERE groupid = :groupid
                                AND attendeeid = :aid');
        $stmt->bindValue(':groupid', $_POST['groupid'], PDO::PARAM_INT);
        $stmt->bindValue(':aid', $aid, PDO::PARAM_INT);
        $stmt->execute();
        $result2 = $stmt->fetchAll();
        foreach ($result2 as $row2) { 
            echo '<script type="text/javascript">alert("In the second loop"); </script>';

            // evaluate attendees attendeeid against attend_date_temp attendeeid
            if($row2['attendeeid'] != $aid){ 

                // Load the flush Table with the IDs from the selected group
                if($_SESSION['flush'] == 0) {
                    $stmt = $db->prepare('INSERT INTO flush (attendeeid, memberid)
                                                    VALUES(:attendeeid, :memberid)');
                    $stmt->bindValue(':attendeeid', $aid, PDO::PARAM_INT);
                    $stmt->bindValue(':memberid', $_SESSION['memberid'], PDO::PARAM_INT);
                    $stmt->execute();
                } 
                if($aaa == 0) {
                    echo "<option value='Select'>Select</option>";
                    echo "<option value=".$aid.">".$lname.", ". $fname."</option>"; 
                    $aaa = 1;
                } else { 
                    echo "<option value=".$aid.">".$lname.", ". $fname."</option>"; 
                }  
            }  
        }  
    }

To do a join you would do something like this:-

$stmt = $db->prepare('SELECT a.attendeeid, fname, lname, a.groupid, a.memberid, s.attendeeid, suspend, adt.attendeeid AS adt_attendeeid, adt.memberid AS adt_memberid
                        FROM attendees AS a
                        INNER JOIN suspended AS s ON a.attendeeid = s.attendeeid 
                        LEFT OUTER JOIN attend_date_temp adt ON adt.groupid = a.groupid AND adt.attendeeid = a.attendeeid
                        WHERE a.memberid = :memberid
                        AND suspend = "N"
                        AND a.groupid = :groupid
                        AND adt.groupid IS NULL
                        ORDER BY lname');
$stmt->bindValue(':memberid', $_SESSION["memberid"], PDO::PARAM_INT);
$stmt->bindValue(':groupid', $_POST['groupid'], PDO::PARAM_INT);
$stmt->execute();

EDIT

Think it can be more simply done like this (not tested so please excuse any typos)

<?php

    $first = true;

/* Load the Select Box with names, less the ones found in attend_date_temp Table. */
    $stmt = $db->prepare('SELECT a.attendeeid, fname, lname
                            FROM attendees AS a
                            INNER JOIN suspended AS s ON a.attendeeid = s.attendeeid 
                            LEFT OUTER JOIN attend_date_temp adt ON adt.groupid = a.groupid AND adt.attendeeid = a.attendeeid
                            WHERE a.memberid = :memberid
                            AND suspend = "N"
                            AND a.groupid = :groupid
                            AND adt.groupid IS NULL
                            ORDER BY lname');
    $stmt->bindValue(':memberid', $_SESSION["memberid"], PDO::PARAM_INT);
    $stmt->bindValue(':groupid', $_POST['groupid'], PDO::PARAM_INT);
    $stmt->execute();
    $result = $stmt->fetchAll();
    foreach($result as $row)
    {
        $aid = $row[0];
        $lname = $row[2];
        $fname = $row[1];

        // Load the flush Table with the IDs from the selected group
        if($_SESSION['flush'] == 0) 
        {
            $stmt = $db->prepare('INSERT INTO flush (attendeeid, memberid)
                                            VALUES(:attendeeid, :memberid)');
            $stmt->bindValue(':attendeeid', $aid, PDO::PARAM_INT);
            $stmt->bindValue(':memberid', $_SESSION['memberid'], PDO::PARAM_INT);
            $stmt->execute();
        } 
        if($first) 
        {
            echo "<option value='Select'>Select</option>";
            echo "<option value='".$aid."'>".$lname.", ". $fname."</option>"; 
            $first = false;
        } 
        else 
        { 
            echo "<option value='".$aid."'>".$lname.", ". $fname."</option>"; 
        }  
    }