J'ai du mal à faire fonctionner correctement une boucle foreach lors de la génération d'un e-mail. J'ai cherché des réponses et j'ai trouvé des instructions pour insérer une boucle foreach dans un e-mail, mais rien sur la boucle ne fonctionne pas.

J'essaie d'envoyer par e-mail les reçus de commande aux clients après avoir passé une commande, et tout ce qui se trouve dans l'e-mail est livré à l'exception de la liste des articles.

J'essaierai d'inclure autant que possible ma logique: lorsque la commande est passée, le tableau des articles du panier est sérialisé puis stocké dans la base de données. Une fois que le processeur de paiement a déclaré que le paiement a été effectué avec succès, j'affiche une page de reçu sur le site Web que l'utilisateur peut imprimer. Les articles de la commande sont extraits de la base de données comme suit:

$stmt = $dbh->prepare("SELECT * FROM *table* WHERE orderID = :q0")
$stmt->bindValue(":q0",$orderNum)
$stmt->execute();
foreach($stmt as $row) {
    $items = unserialize($row['order_contents']);
}

À ce stade, si je fais écho à $ items, je vois un tableau des articles de la commande. Jusqu'ici tout va bien.

Maintenant que j'utilise PDO, une boucle foreach dans la requête n'est pas quelque chose que j'ai compris comment faire. Au lieu de cela, j'ai initialisé une variable pour contenir les éléments de la boucle foreach:

foreach($items as $prod_id => $value) {
    $q .= $prod_id . ',';
}
$q = substr($q, 0, -1);

Cela stocke le tableau dans une variable que je peux maintenant utiliser dans l'instruction PDO pour la requête suivante:

$stmt2 = $dbh->prepare("SELECT * FROM *productTable* WHERE prod_ID IN ($q)");
$stmt2->execute();
foreach($stmt2 as $row) {
$itemName = htmlentities(strip_tags($row['prod_name']));
$id = htmlentities(strip_tags($row['prod_ID']));
$qty = htmlentities(strip_tags($items[$prod_id]['quantity']));
$price = $items[$prod_id]['price'];
echo "
    <tr>
        <td>".$qty."</td>
        <td>".$itemName."</a></td>
        <td>".$price."</td>                        
    </tr>";
} // THIS CODE WORKS. I can see each item from the order as a new row in the table

Encore une fois, tout va bien. Je peux exécuter une boucle foreach pour faire écho aux éléments sur la page, et ils s'affichent tous avec le nom d'élément approprié ainsi que d'autres informations de la table que j'ai omises de cet exemple.

Passez à la fin du fichier, et j'ai le script suivant qui ne fonctionne pas et je ne peux pas comprendre pourquoi. L'e-mail est envoyé avec succès, mais aucun des produits de la boucle foreach n'apparaît dans l'e-mail.

$to = 'user@email.com'
$subject = 'Your order receipt for order '.$orderNum
$headers = 'From: orders@website.com'."\r\n".
           'Reply-To: orders@website.com'."\r\n".
           'Content-Type: text/html; charset=UTF-8'."\r\n".
           'X-Mailer: PHP/'.phpversion();
$message =  '<html><body>';
$message .= '<h2>Thanks for your purchase!</h2><br>';
$message .= '<p>Here are the details of your order number '.$orderRef.':<br><table>';
$message .= '
<tr style="width: 100%;">
    <th scope="col" style="width: 20%;">Quantity:</th>
    <th scope="col" style="width: 60%;">Name:</th>
    <th scope="col" style="width: 20%;">Price:</th>
</tr>
';
foreach ($stmt2 as $row) {
    $message .= "
    <tr>
        <td>".$qty."</td>
        <td>".$itemName."</td>
        <td>".$price."</td>                        
    </tr>"; //THIS CODE DOESN'T WORK, Even though it's using the same variables as the loop from above. 
}
$message .= '</table><br>';
$message .= 'If you have any questions about your order, please call us at <b>XXX-XXX-XXXX</b>';
$message .= '</body></html>';
mail($to, $subject, $message, $headers);

L'e-mail envoie et je vois tout avant et après la boucle foreach, mais je ne vois pas les éléments réels générés. Après le code de l'e-mail, je peux faire écho aux variables sur la page et elles s'affichent toutes correctement, de sorte que les variables sont toujours déclarées.

Informations supplémentaires qui peuvent ou non être pertinentes: j'essaie d'exécuter ce code sur un VPS fraîchement imaginé avec Ubuntu 14.04. Je viens d'installer un certificat SSL lundi, j'ai récemment installé UFW sur mon VPS. Les ports SMTP, IMAP et UTP ne sont pas bloqués. PHP version 5.5.9-1ubuntu4.21

Voici une capture d'écran de la sortie de l'e-mail: capture d'écran de l'e-mail

Edit: Les variables étaient déjà définies après la première instruction foreach ($ stmt2 as $ row). J'ai ajouté le code supplémentaire pour refléter cela.

0
Mark 20 avril 2017 à 19:51

3 réponses

Meilleure réponse

$stmt2 n'est pas un tableau, c'est un générateur. Entre autres choses, cela permet de charger uniquement les lignes en mémoire au besoin, plutôt que de devoir lire le tout en mémoire à la fois.

Le hic, c'est que vous ne pouvez pas foreach deux fois. Vous devrez le convertir en un tableau réel. Je n'ai pas testé, mais vous pourrez peut-être le faire avec $itemdata = iterator_to_array($stmt2) - à défaut, $itemdata[] = $row seulement dans votre premier foreach vous permettra de vous référer à ce $itemdata tableau plus tard .

1
Niet the Dark Absol 20 avril 2017 à 16:58

Je pense que le problème est dans la boucle foreach.

foreach ($stmt2 as $row) {
    $message .= "
    <tr>
        <td>".$qty."</td> // $qty is undefined! You should use $row['qty'] or $row->qty
        <td>".$itemName."</td> // $itemName is not defined
        <td>".$price."</td> // $price is not defined
    </tr>";
}

J'espère que ça aide.

0
Hossein 20 avril 2017 à 17:00

La solution avec laquelle j'ai fini était d'ajouter à nouveau la requête SQL, à l'intérieur du code de l'e-mail:

$message .= '<p>Here are the details of your order number '.$orderRef.':<br>
<table>';
$message .= '
<tr style="width: 100%;">
    <th scope="col" style="width: 20%;">Quantity:</th>
    <th scope="col" style="width: 60%;">Name:</th>
    <th scope="col" style="width: 20%;">Price:</th>
</tr>
';
$stmt2 = $dbh->prepare("
SELECT * FROM products WHERE prod_ID IN ($q) ORDER BY prod_id ASC
");
$stmt2->execute();
while ($row = $stmt2->fetch(PDO::FETCH_ASSOC)) {
    $itemName = htmlentities(strip_tags($row['prod_name']));
    $id = htmlentities(strip_tags($row['prod_ID']));
    $qty = htmlentities(strip_tags($items[$prod_id]['quantity']));
    $price = $items[$prod_id]['price'];

    $message .= "
    <tr>
        <td>".$qty."</td>
        <td>".$itemName."</td>
        <td>".$price."</td>                        
    </tr>";
    }
$message .= '</table><br>';

Puis le reste du code. Cela semble fonctionner maintenant, mon email de test a montré les deux éléments de la commande de test.

Merci à tous pour vos suggestions.

0
Mark 20 avril 2017 à 17:19