Search code examples
phparraysstringvariable-names

array_combine with same key names


I am trying to save some information from an email to an array. The email contents are html tables and i am using the DOMDocument method getElementsByTagName('td') to receive all the td's.

In an for loop i iterate through all emails in an mail folder and save the information in an array. That looks like this:

function getMails()
{
    $mailbox = imap_mailboxmsginfo($this->imap);
    $msglength = $mailbox->Nmsgs;
    $domhtml = new DOMDocument();
    $arraykeys = [];
    $arrayvalues = [];
    // loop a) to iterate through all mails in the folder
    for ($i = 1; $i <= $msglength; $i++)
    {
        $html = imap_fetchbody($this->imap, $i, '2');
        $domhtml->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
        $tabledatas = $domhtml->getElementsByTagName('td');
        // loop aa) to save the heading td's in the html mail in an array
        for ($y = 0; $y < $tabledatas->length; $y+=2)
        {
            $arraykeys[] = rtrim($tabledatas->item($y)->nodeValue, ':');
        }
        // loop ab) to save the content td's in the html mail in an array
        for ($z = 1; $z < $tabledatas->length; $z+=2)
        {
            $arrayvalues[] = ($tabledatas->item($z)->nodeValue);
        }
        // combine the 2 arrays into one array with all td's information      
        $array = array_combine($arraykeys, $arrayvalues);
  }
  imap_close($this->imap);
}

Why i use one array for the td heading and one for the td content can be explained by looking at the html from the mail:

<h2>Section one</h2>

<table>
    <tr>
        <td>Heading_value_a:</td>
        <td>Content_value_a</td>
    </tr>
    <tr>
        <td>Heading_value_b:</td>
        <td>Content_value_b</td>
    </tr>
    <tr>
        <td>Heading_value_c:</td>
        <td>Content_value_c</td>
    </tr>
</table>

<h2>Section two</h2>

<table>
    <tr>
        <td>Heading_value_d:</td>
        <td>Content_value_d</td>
    </tr>
    <tr>
        <td>Heading_value_e:</td>
        <td>Content_value_e</td>
    </tr>
    <tr>
        <td>Heading_value_f:</td>
        <td>Content_value_f</td>
    </tr>
</table>

<h2>Section three</h2>

<table>
    <tr>
        <td>Heading_value_g:</td>
        <td>Content_value_g</td>
    </tr>
    <tr>
        <td>Heading_value_h:</td>
        <td>Content_value_h</td>
    </tr>
    <tr>
        <td>Heading_value_i:</td>
        <td>Content_value_i</td>
    </tr>
</table>

<h2>Subsection three</h2>

<table>
    <tr>
        <td>Heading_value_g:</td>
        <td>Content_value_g</td>
    </tr>
    <tr>
        <td>Heading_value_h:</td>
        <td>Content_value_h</td>
    </tr>
    <tr>
        <td>Heading_value_i:</td>
        <td>Content_value_i</td>
    </tr>
</table>

That gives me this array:

Array
(
    [Heading_value_a] => Content_value_a
    [Heading_value_b] => Content_value_b
    [Heading_value_c] => Content_value_c
    [Heading_value_d] => Content_value_d
    [Heading_value_e] => Content_value_e
    [Heading_value_f] => Content_value_f
    [Heading_value_g] => Content_value_g
    [Heading_value_h] => Content_value_h
    [Heading_value_i] => Content_value_i
)

When i combine the two array into one, i lose the information from the subsection three, because the td headings from section three have the same name as the subsection three headings and the new array would have indexes with the same name, thats why i need to rename the array indexes for the subsection three. The subsection three td's have the index 42 and higher. I figured out how to give the new array some other index names to save the information, by adding the current td index to the array index name in the loop aa):

if ($y <= 41)
{
    $arraykeys[] = rtrim($tabledatas->item($y)->nodeValue, ':');
} else 
  {
    $arraykeys[] = rtrim($tabledatas->item($y)->nodeValue, ':').$y;
  }

That gives me this array:

Array
(
   [Heading_value_a] => Content_value_a
   [Heading_value_b] => Content_value_b
   [Heading_value_c] => Content_value_c
   [Heading_value_d] => Content_value_d
   [Heading_value_e] => Content_value_e
   [Heading_value_f] => Content_value_f
   [Heading_value_g] => Content_value_g
   [Heading_value_h] => Content_value_h
   [Heading_value_i] => Content_value_i
   [Heading_value_g42] => Content_value_g
   [Heading_value_h44] => Content_value_h
   [Heading_value_i46] => Content_value_i
)

Is there a way to add numbers from 2 and higher to the new array index name? If the mail has more subsections three then in the new array index would appear, [Heading_value_g2], [Heading_value_h2], [Heading_value_i2], [Heading_value_g3], [Heading_value_h3], [Heading_value_i3] and so one. My goal is the following array:

Array
(
   [Heading_value_a] => Content_value_a
   [Heading_value_b] => Content_value_b
   [Heading_value_c] => Content_value_c
   [Heading_value_d] => Content_value_d
   [Heading_value_e] => Content_value_e
   [Heading_value_f] => Content_value_f
   [Heading_value_g] => Content_value_g
   [Heading_value_h] => Content_value_h
   [Heading_value_i] => Content_value_i
   [Heading_value_g2] => Content_value_g
   [Heading_value_h2] => Content_value_h
   [Heading_value_i2] => Content_value_i
)

I had the idea to initialise a count variable like $c in the aa) loop with the if condition and set it to the td's value with an ternary operator, the steps for the td's are from 42 to 64 for subsection three one, 66 to 88 for the subsection three two and so one:

for ($y = 0; $y < $tabledatas->length; $y+=2)
{
    if ($y < 42)
    {
        $arraykeys[] = rtrim($tabledatas->item($y)->nodeValue, ':');
    } else
    {
        $c = ($y >= 42 && $y <= 64) ? '2' : ($y >= 66 && $y <= 88 ? '3' : '');
        $arraykeys[] = rtrim($tabledatas->item($y)->nodeValue, ':').$c;
    }
}

This works, and i receive the result i wish, but it's not dynamic enough, what if there are more then one or two subsections three, then i had to write the ternary operator with more conditions like this one to work with 3 subsections three:

$c = ($y >= 42 && $y <= 64) ? '2' : ($y >= 66 && $y <= 88 ? '3' : ($y >= 90 && $y <= 112 ? '4' : 'and more conditions' ));

has anyone a hint how i could manage this to work with an infinite number of subsections three? Thank you in advance.


Solution

  • You should consider "chunking" a master associative array of elements to fix the original issue of duplicate key overwriting:

    function.array-chunk.php