Foreach loop returns only first index on multidimensional array PHP
Asked Answered
H

2

5

Let me explain my situation, I'm making a mailing template for my company. This mailing template has to be completely in HTML. The mailing template contains different products from our shop. The template has boxes with information about the products. let me show you my template:

mailing-template.html

         <div>
                    ##PRODUCT_NAME##                     <br />    
                    Onderdeel Nr: ##PRODUCT_ID##         <br />  
                    Merk: ##PRODUCT_BRAND##              <br />  
                    Prijs: €##PRODUCT_PRICE##            <br />
         </div>

As you can probably tell, ##PRODUCT_INFORMATION# are the places my product information will come. With some help of PHP i can replace this. I get my product information from different arrays looking like this:

arrays

$products = array
(
    array
    (
        'product_id' => 'RD55559955',
        'product_name' => 'Ontsteking (DI) Cassette Zwart Origineel Saab 9-3/9-5',
        'price_excl' => 22600,
        'product_brand' => 'Origineel Saab',
    ),

    array
    (
        'product_id' => 'RD55559955',
        'product_name' => 'een ander product',
        'price_excl' => 22600,
        'product_brand' => 'Origineel Saab',
    ),

    array
    (
        'product_id' => 'RD55559955',
        'product_name' => 'nog een ander product',
        'price_excl' => 22600,
        'product_brand' => 'Origineel Saab',
    )
);

Now let me show you how i replace the information:

createTemplate.php

//get content from mailing-template
$template = file_get_contents(dirname(__FILE__).'/mailing-template.html');
$content = $template;

foreach ($products as $product){

//replace placeholders with actual product data
$content = str_ireplace('##PRODUCT_ID##', $product['product_id'], $content);
$content = str_ireplace('##PRODUCT_NAME##', $product['product_name'], $content);
$content = str_ireplace('##PRODUCT_PRICE##', round($product['price_excl']/100, 2), $content);
$content = str_ireplace('##PRODUCT_BRAND##', $product['product_brand'], $content);


//echo the template
echo $content;
}

I'm using str_ireplace to replace the information.

What i want: So what i want is to display a product information box per array.

Problem: What it does is display three product boxes from only the first array.

Question: Does anyone know how i can display three boxes from all different three arrays?

This question is quite big for how simple the answer probably is, but, i have been stuck for quite some time now so i hoped someone here could help me out here. Thanks for taking your time, appreciate all the help i can get!

Im really new to this all, including stackoverflow so correct me in anyway you can. :)

Note: When i echo $product['product_name'] outside $content it does display three different names. It doesnt work whenever i edit the $content. I just dont seem to get why.

Heterography answered 11/10, 2019 at 11:9 Comment(0)
B
2

There are no remaining placeholders after the first loop.

You need a fresh template on each iteration.

I also don't see the need for case_insensitive replacements.

The first two parameters of str_replace() will accept arrays, so you can reduce the total function calls to one.

Tested Code: (Demo)

foreach ($products as $product) {
    echo str_replace(
             ['##PRODUCT_ID##', 
              '##PRODUCT_NAME##',
              '##PRODUCT_PRICE##',
              '##PRODUCT_BRAND##'],
             [$product['product_id'],
              $product['product_name'],
              round($product['price_excl']/100, 2),
              $product['product_brand']],
             $content
         );
}

Output:

<div>
     Ontsteking (DI) Cassette Zwart Origineel Saab 9-3/9-5                     <br />    
     Onderdeel Nr: RD55559955         <br />  
     Merk: Origineel Saab              <br />  
     Prijs: €226            <br />
</div><div>
     een ander product                     <br />    
     Onderdeel Nr: RD55559955         <br />  
     Merk: Origineel Saab              <br />  
     Prijs: €226            <br />
</div><div>
     nog een ander product                     <br />    
     Onderdeel Nr: RD55559955         <br />  
     Merk: Origineel Saab              <br />  
     Prijs: €226            <br />
</div>
Boson answered 11/10, 2019 at 11:18 Comment(0)
D
4

You're destroying your template with the first loop

move $content = $template; to within your foreach loop so that it gets the "fresh" template source each time.

foreach ($products as $product){
  $content = $template;
Dorsman answered 11/10, 2019 at 11:17 Comment(2)
Did you happen to remove your upvote from my answer? It had more upvotes when I went to bed. If so, could you explain why? It is correct, tested, and shows the OP not only to how to fix the issue, but improve the overall performance of the snippet. I simply don't understand the retraction.Boson
@Boson Must have been a misclick, there was no negative intention otherwise.Dorsman
B
2

There are no remaining placeholders after the first loop.

You need a fresh template on each iteration.

I also don't see the need for case_insensitive replacements.

The first two parameters of str_replace() will accept arrays, so you can reduce the total function calls to one.

Tested Code: (Demo)

foreach ($products as $product) {
    echo str_replace(
             ['##PRODUCT_ID##', 
              '##PRODUCT_NAME##',
              '##PRODUCT_PRICE##',
              '##PRODUCT_BRAND##'],
             [$product['product_id'],
              $product['product_name'],
              round($product['price_excl']/100, 2),
              $product['product_brand']],
             $content
         );
}

Output:

<div>
     Ontsteking (DI) Cassette Zwart Origineel Saab 9-3/9-5                     <br />    
     Onderdeel Nr: RD55559955         <br />  
     Merk: Origineel Saab              <br />  
     Prijs: €226            <br />
</div><div>
     een ander product                     <br />    
     Onderdeel Nr: RD55559955         <br />  
     Merk: Origineel Saab              <br />  
     Prijs: €226            <br />
</div><div>
     nog een ander product                     <br />    
     Onderdeel Nr: RD55559955         <br />  
     Merk: Origineel Saab              <br />  
     Prijs: €226            <br />
</div>
Boson answered 11/10, 2019 at 11:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.