title: Make HTML table from array returned from execute_db in PHP - entries duplicated
body: <p>I want to populate a html table from the results of a SQL query, the fields included will vary depending on choices the user makes so I want to autmatically set the headings etc based on what is in the results of the query. I found the array_to_table function on the website <a href="https://inkplant.com/code/array-to-table" rel="nofollow noreferrer">https://inkplant.com/code/array-to-table</a> and it does what I want except the data is duplicated:-</p>
  <p><strong>Expected result</strong></p>
  <pre><code>Formation       Play    
  A               SW
  S               DL
  </code></pre>
  <p><strong>Actual Result</strong></p>
  <pre><code>Formation   0   Play    1
  A           A   SW      SW
  S           S   DL      DL 
  </code></pre>
  <p>I think it may be be to do with the type of array I'm creating but I'm unsure how to alter the code to generate my expected result.  I'm not sure if I should create the array in a different way or whether (or how) I should change the function to work with the type of array I have.</p>
  <p>#SQL for creating example table</p>
  <pre><code>CREATE TABLE `example` ( `id` INT NOT NULL AUTO_INCREMENT , `form` VARCHAR(10) NOT NULL , `playcall` VARCHAR(10) NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB;
  </code></pre>
  <p>#Sample data</p>
  <pre><code>INSERT INTO `example` (`id`, `form`, `playcall`) VALUES (NULL, 'A', 'SW'), (NULL, 'S', 'DL');
  </code></pre>
  <p>#mycode</p>
  <pre><code>$sql = &quot;SELECT `form` as 'Formation',`playcall` as 'Playcall' FROM `example` ORDER BY `form` DESC&quot;;       
  $res = execute_db($sql3 $conn);
     
  $caption = &quot;Example table&quot;;
       
  echo array_to_table($res,$caption);
  </code></pre>
  <p>#function</p>
  <pre><code>function array_to_table($data,$caption,$args=false) {
      if (!is_array($args)) { $args = array(); }
      foreach (array('class','column_widths','custom_headers','format_functions','nowrap_head','nowrap_body','capitalize_headers') as $key) {
          if (array_key_exists($key,$args)) { $$key = $args[$key]; } else { $$key = false; }
      }
      if ($class) { $class = ' class=&quot;'.$class.'&quot;'; } else { $class = ''; }
      if (!is_array($column_widths)) { $column_widths = array(); }
  
      //get rid of headers row, if it exists (headers should exist as keys)
      if (array_key_exists('headers',$data)) { unset($data['headers']); }
  
      $t=&quot;&lt;table style='width:40%'  class='w3-table w3-striped w3-bordered'&gt;&quot;;
      $t .= $caption;
      
      $i = 0;
      foreach ($data as $row) {
          $i++;
          //display headers
          if ($i == 1) { 
              foreach ($row as $key =&gt; $value) {
                  if (array_key_exists($key,$column_widths)) { $style = ' style=&quot;width:'.$column_widths[$key].'px;&quot;'; } else { $style = ''; }
                  $t .= '&lt;col'.$style.' /&gt;';
              }
              $t .= '&lt;thead&gt;&lt;tr&gt;';
              foreach ($row as $key =&gt; $value) {
                  if (is_array($custom_headers) &amp;&amp; array_key_exists($key,$custom_headers) &amp;&amp; ($custom_headers[$key])) { $header = $custom_headers[$key]; }
                  elseif ($capitalize_headers) { $header = ucwords($key); }
                  else { $header = $key; }
                  if ($nowrap_head) { $nowrap = ' nowrap'; } else { $nowrap = ''; }
                  $t .= '&lt;td'.$nowrap.'&gt;'.$header.'&lt;/td&gt;';
              }
              $t .= '&lt;/tr&gt;&lt;/thead&gt;';
          }
  
          //display values
          if ($i == 1) { $t .= '&lt;tbody&gt;'; }
          $t .= '&lt;tr&gt;';
          foreach ($row as $key =&gt; $value) {
              if (is_array($format_functions) &amp;&amp; array_key_exists($key,$format_functions) &amp;&amp; ($format_functions[$key])) {
                  $function = $format_functions[$key];
                  if (!function_exists($function)) { custom_die('Data format function does not exist: '.htmlspecialchars($function)); }
                  $value = $function($value);
              }
              if ($nowrap_body) { $nowrap = ' nowrap'; } else { $nowrap = ''; }
              $t .= '&lt;td'.$nowrap.'&gt;'.$value.'&lt;/td&gt;';
          }
          $t .= '&lt;/tr&gt;';
      }
      $t .= '&lt;/tbody&gt;';
      $t .= '&lt;/table&gt;';
      return $t;
  }
  </code></pre>
  <p>EDIT: Based on the tip from <a href="https://stackoverflow.com/users/13851118/dhnwebpro">https://stackoverflow.com/users/13851118/dhnwebpro</a> I dumped the array to see what it contained:-</p>
  <p>Array</p>
  <pre><code>(
      [0] =&gt; Array
          (
              [Formation] =&gt; A
              [0] =&gt; A
              [Playcall] =&gt; SW
              [1] =&gt; Sw
          )
  
      [1] =&gt; Array
          (
              [Formation] =&gt; S
              [0] =&gt; S
              [Playcall] =&gt; DL
              [1] =&gt; DL
          )
  
  )
  </code></pre>
  <p>EDIT2: I changed the format of the query and got it working:-</p>
  <p>$res3 = $conn-&gt;query($sql3)-&gt;fetchAll(PDO::FETCH_ASSOC);</p>
  <p>Fetch both was indeed the default and I was able to override that with the above statement.</p>