PHP loop to generate an HTML form for the days in the coming week There are two arrays, $states and $weekdays. I want to loop through them to create a form, an HTML table, or possibly some other element).

Here's my example:

// addDay() Adds 1 day to the date
// format() Returns a date in a new format
// get_date() returns todays date in unix

$weekdays = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ];
$states   = [ 'start', 'finish', 'total', 'overtime' ];
$date     = get_date();

foreach ( $states as $state ) { ?&gt;
  &lt;tr class="&lt;?php echo $state; ?&gt;"&gt;
    &lt;th&gt;&lt;?php echo $state; ?&gt;&lt;/th&gt;
    &lt;?php
    $d = 0;
    foreach ( $weekdays as $weekday ) { ?&gt;
      &lt;td&gt;
        &lt;input name="date&lt;?php echo $date-&gt;addDay( $d )-&gt;format('[Y][m][d]') . '[' . $state . ']'; ?&gt;" /&gt;
      &lt;/td&gt;
    &lt;?php
    $d++;
      } ?&gt;
  &lt;/tr&gt;
&lt;?php
}


I think the code can be cleaner. Ignore the fact that there aren't comments. Focus on the HTML / PHP intertwining. Can it be separated further or tidier?

Is there a method of sprintf but for sections of code perhaps? or would you echo the whole thing with double quotes for the variables?

Note — I am using PHP7, so be as fancy as you want with the latest syntax;
Initial Thoughts

Initially I was thinking of suggesting a view class that could hold the states and weekdays in instance variables, then have methods to get the header for each state and then display the cells for each weekday, but that seems like a lot of extra overhead just to display a table, and wouldn't provide the desired separation of business logic and display templates.

Simple improvements

As GrumpyCrouton mention in the SO answer, PHP Short echo tags could be used to shorten the inline echo statements (i.e. &lt;?php echo to &lt;?=).

$d could be eliminated by using the associative array syntax of foreach


  foreach (array_expression as $key => $value)
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;statement
  1


foreach($weekdays as $d =&gt; $weekday) {
    //$d doesn't need to be incremented since it is the keys - e.g. 0, 1, 2, etc.
}


Or just used array_keys() since the weekday value isn't used...

foreach(array_keys($weekdays) as $d) {
    //$d doesn't need to be incremented since it is the keys - e.g. 0, 1, 2, etc.
}


One could define a template using Heredoc syntax, like:

$cellTemplate = &lt;&lt;&lt;CELL
&lt;td&gt;
    &lt;input name="date-%s" /&gt;
&lt;/td&gt;
CELL;


Then that could be used for each table cell:

foreach ( $states as $state ) { ?&gt;
  &lt;tr class="&lt;?= $state; ?&gt;"&gt;
    &lt;th&gt;&lt;?= $state; ?&gt;&lt;/th&gt;
    &lt;?php
    foreach ( $weekdays as $d =&gt; $weekday ) { 
        $dateName = $date-&gt;addDay( $d )-&gt;format('[Y][m][d]') . '[' . $state . ']';
        echo sprintf($cellTemplate, $dateName);
      } 
      ?&gt;
  &lt;/tr&gt;
&lt;?php
}
?&gt;


A demonstration can be seen here. Note that instead of using the Carbon DateTime I am using PHP's DateTime class along with DateInterval to accomplish the date addition with DateTime::add().

Template Engines

One could also utilize a template engine, like Smarty, Symfony’s Twig, Laravel’s Blade, etc.

Here is an example with a Smarty template. I like bumperbox's notion of storing the formatted weekdays in an array and using that in later on. That array could also be generated using array_map() (though accessing $date inside the callback would require a use statement):

$formattedWeekdays = array_map(function($d, $weekday) use ($date) {
    return $date-&gt;addDay( $d )-&gt;format('[Y][m][d]');
}, array_keys($weekdays), $weekdays);
$smarty-&gt;assign('states', $states);
$smarty-&gt;assign('formattedWeekdays', $formattedWeekdays);
$smarty-&gt;display('../templates/weekdays.tpl');


And that template file (i.e. weekdays.tpl) might look like this:

&lt;table&gt;
    {foreach $states as $state}
    &lt;tr class="{$state}"&gt;
        &lt;th&gt;{$state}&lt;/th&gt;
        {foreach $formattedWeekdays as $formattedWeekday }
        &lt;td&gt;
            &lt;input name="date-{$formattedWeekday}[{$state}]" /&gt;
        &lt;/td&gt;
        {/foreach}
    &lt;/tr&gt;
    {/foreach}
&lt;/table&gt;    


That way the display logic is separate from the business logic. As this wikibooks page alludes to, the HTML is separated from the PHP code so multiple people (e.g. graphics designer, developers, etc.) can manage the separate parts since they are de-coupled.



1http://php.net/manual/en/control-structures.foreach.php