Verbose problem I would like simplifying because there are lots more script to follow :)

I am trying to use PHP to populate a HTML form and to retain the $_POST values to assist in editing.

Below is the script showing only two HTML input blocks - there is going to be many more!

I have unsuccessfully tried calling a common function to populate the form and would be grateful if someone could simplify the process to cater for the impending additions:

<?php 
declare(strict_types=1);
# echo error_reporting();
# echo ini_get('display_errors');
#  die;
$title  = 'Test Data';

if(0) : $_POST = []; endif;
$_POST['xxx'][0][0]   = $_POST['xxx'][0][0] ?? 'xxx00 NOT SET';
$_POST['xxx'][0][1]   = $_POST['xxx'][0][1] ?? 'xxx01 NOT SET';
$_POST['xxx'][0][2]   = $_POST['xxx'][0][2] ?? 'xxx02 NOT SET';
$_POST['xxx'][1][0]   = $_POST['xxx'][1][0] ?? 'xxx10 NOT SET';
$_POST['xxx'][1][1]   = $_POST['xxx'][1][1] ?? 'xxx11 NOT SET';
$_POST['xxx'][1][2]   = $_POST['xxx'][1][2] ?? 'xxx12 NOT SET';

?><!DOCTYPE HTML><html  lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1">
<title> <?= $title ?> </title>
<!--
<link rel="stylesheet" href="style-001.css" media="screen">
-->
<style> 
  h2   {margin: 0.42em 0 0; padding: 0;}
  h3   {display: none; text-align: center; margin: 2em auto;}
  dt   {font-weight: 700;}
  label{display: inline-block; width: 11%;}
  input{width:80%; background-color: #dfd;}
  .bd1 {border: solid 1px #ccc;}
  .bgs {background-color: snow; color: #333;}
  .mga {margin: 0 auto;}
  .p42 {padding: 0.42em;}
  .tac {text-align: center;} .tar {text-align: right;}
  .w88 {width: 88%; max-width: 888px;}
</style>

</head>
<body>

<pre> 
  <?php 
    echo 'TEST: $_POST ==> '; 
    print_r($_POST); 
  ?> 
</pre>

  <div class="w88 mga bd1 bgs"> 
    <h1> <?= $title ?> </h1>
    <form action="?" method="post">

      <dl class="dib bd1">
        <dt> Test Data 0 </dt>
        <dd>
          <label> Jack </label>
            <input type="text" name="<?= $_POST['xxx'][0][0] ?>" value="<?= $_POST['xxx'][0][0] ?>">
            <br>
          <label> Fred  </label>
            <input type="text" name="<?= $_POST['xxx'][0][1] ?>" value="<?= $_POST['xxx'][0][1] ?>">
            <br>
          <label> Harry  </label>
            <input type="text" name="<?= $_POST['xxx'][0][2] ?>" value="<?= $_POST['xxx'][0][1] ?>">
            <br><br>
        </dd>   
      </dl>
      
      <dl class="dib bd1">
        <dt> Test Data 1 </dt>
        <dd>
          <label> Jack </label>
            <input type="text" name="<?= $_POST['xxx'][1][0] ?>" value="<?= $_POST['xxx'][1][0] ?>">
            <br>
          <label> Fred  </label>
            <input type="text" name="<?= $_POST['xxx'][1][1] ?>" value="<?= $_POST['xxx'][1][1] ?>">
            <br>
          <label> Harry  </label>
            <input type="text" name="<?= $_POST['xxx'][1][2] ?>" value="<?= $_POST['xxx'][1][2] ?>">
            <br><br>
        </dd>   
      </dl>

      <input type="submit" value="submit">
    </form> 
  </div>  

</body>
</html>


for ($x = 0; $x < 2; $x++) {
    for ($y = 0; $y < 3; $y++) {
        $_POST['xxx'][$x][$y] = $_POST['xxx'][$x][$y] ?? "xxx$x$y NOT SET";
    }
}

If you’re on PHP 7.4 you can replace

$_POST['xxx'][$x][$y]   = $_POST['xxx'][$x][$y] ?? "xxx$x$y NOT SET";

with

$_POST['xxx'][$x][$y] ??= $_POST['xxx'][$x][$y];

Also, I’d personally put the new values somewhere else than back in $_POST, just so you can be sure it was processed somehow and not raw post data, but that’s just me.

1 Like

To clarify, is ‘xxx’ a single, static string?
Cause… this just screams out for nested foreaches.

  <dl class="dib bd1">
    <dt> Test Data 0 </dt>
    <dd>
      <label> Jack </label>
        <input type="text" name="<?= $_POST['xxx'][0][0] ?>" value="<?= $_POST['xxx'][0][0] ?>">
        <br>
      <label> Fred  </label>
        <input type="text" name="<?= $_POST['xxx'][0][1] ?>" value="<?= $_POST['xxx'][0][1] ?>">
        <br>
      <label> Harry  </label>
        <input type="text" name="<?= $_POST['xxx'][0][2] ?>" value="<?= $_POST['xxx'][0][1] ?>">
        <br><br>
    </dd>   
  </dl>

Take that row as the ‘exemplar’, then:

<?php
$labels = ['Jack','Fred','Harry']
foreach($_POST['xxx'] as $idx => $data) { ?>
      <dl class="dib bd1">
        <dt> Test Data <?= $idx; ?> </dt>
        <dd>
           <?php foreach($data as $inneridx => $row) { ?>
          <label><?= $labels[$inneridx] ?></label>
            <input type="text" name="<?= $row[$inneridx] ?>" value="<?= $row[$inneridx] ?>">
           <?php } ?>
        </dd>   
      </dl>
<?php } ?>

This block then presents all of your data.
(Note: Use CSS instead of HTML tags to space your entries. It’ll be a lot more manageable!)

As for the not sets, if you’re predefining your labels (IE: You expect to have X ‘columns’ in the data), tweak Remon’s example slightly to make it expand to fit the data:

for ($x = 0; $x < count($_POST['xxx']); $x++) {
    for ($y = 0; $y < count($labels); $y++) {
        $_POST['xxx'][$x][$y] = $_POST['xxx'][$x][$y] ?? "xxx$x$y NOT SET";
    }
}

I think it is better to follow @benanamen’s advice and to ignore my feeble attempts.

I was recently landed with the task of administering seven doses of medication from a list in no particular order. It was not easy to glance at the list and to determine the drug and dosage for a particular time of the day. I thought that separating into blocks before and after mealtimes would make it easier but open to any other suggestions.

Following are two links, one showing desired output and the other showing proposed form to input the results. The output is currently hard-coded and I would like to be able to input an unknown amount of medication before and after each mealtime.

https://this-is-a-test-to-see-if-it-works.tk/pop-dosage/index-003.php

https://this-is-a-test-to-see-if-it-works.tk/pop-dosage/index-002.php

So your primary problem is going to be in generating the input form. The processing is easy.

The idea of repeatable sections of data is not new; dynamically inserting new rows into a table is not new either.

What i’d recommend is to intercept the submit button on the form, and have Javascript construct the input array properly.

Also, your not set’s arent going to be not-set. An empty text input is transmitted with the data as the empty string, not omitted.

My knowledge of JavaScript is very limited and prefer CSS and PHP.

To simplify the form perhaps showing the mealtimes and using CSS to accordion about five input fields.

I was also thinking of a"review" submit button and a final “save results” to “my-name.html”. No doubt a password protected edit form feature would also be required in case others modified the dosage!!!

As you mentioned displaying should be quite easy to determine the populated drug dosage and ignore empty fields.

As already mentioned, it’s not hard to lay out the form when you have the main sides defined, which are the “medtime” and fields you wish to use, e.g. Drug, Dose and Time. Setting up a few arrays holding a DB field name and Display name gives you something to loop with. Pretty straight forward.

	$medicationtimes = array(
	 'before_breakfast' => 'Before Breakfast'
	,'after_breakfast' => 'After Breakfast'
	,'before_lunch' => 'Before Lunch'
	,'after_lunch' => 'After Lunch'
	,'before_dinner' => 'Before Dinner'
	,'after_dinner' => 'After Dinner'
	,'bed_time' => 'Bed Time'
	,'odd_balls' => 'Odd Balls'); 
	
	$fields = array('Drug','Dose','Time');

The other varying factor is how many medications per medtime slot. A submit button can easily send the call to add or remove a display row in each of the medtime slots by using the medtime as the submit name [KEY]…

<input type="submit" class="btn btn-primary sm-btn" name="add_med_row['.$medtime.']" value="Add Row" />
<input type="submit" class="btn btn-primary sm-btn" name="remove_med_row['.$medtime.']" value="Remove Row" />

Setting “rows to show” to session allows page to hold while you POST etc and rows can be added like so.

if(isset($_POST['add_med_row'])):
	$timekeys = array_keys($_POST['add_med_row']);
	$timekey = $timekeys[0];
	$_SESSION['rowstoshow'][$timekey]++;
endif;

Having this defined for all time slots allows to to add or subtract those extra input row built with a FOR loop.

for($l=1;$l<=$_SESSION['rowstoshow'][$medtime];$l++):

Then you have all the keys to build your inputs. We use the Medtime, the field and the rows to show for this section as the keys for both the POST[KEYS] holder and the input name [KEYS]. We also built a data array from query DB result for a single patient and use this same array KEY structure to hold that information. All three would look like this.

$datavalue = (!empty($data['medications'][$medtime][$field][$l]) ? $data['medications'][$medtime][$field][$l] : '');
$inputvalue = (!empty($_POST[$medtime][$field][$l]) ? $_POST[$medtime][$field][$l] : $datavalue);

<input type="text" name="'.$medtime.'['.$field.']['.$l.']" value="'.$inputvalue.'" />

Putting the loops and buttons and inputs into a form in a table layout would look something like this.


Built using this code and a sample data array.

<?php
echo '<form action="'.$pagename.'" method="post">'."\r";
	echo '<div class="insertdata">'."\r";  
		
		$patient_id = (!empty($data['patient_info']['patient_id']) ? $data['patient_info']['patient_id'] : '');	
		$patient_name = (!empty($data['patient_info']['patient_name']) ? $data['patient_info']['patient_name'] : '');  
		
		echo '<input type="hidden" name="patient_id" value="'.$patient_id.'">'."\r";	
		echo '<h2>&nbsp;<i>Patient:</i> '.$patient_name.'</h2>'."\r"; 
		
		$cols = count($fields)+1;  
		
		echo '<table>'."\r";
		foreach($medicationtimes as $medtime => $medtimedisplay):
				echo '<tr>
					<th colspan="'.$cols.'"><div class="heading">'.$medtimedisplay.'</div>
						<input type="submit" class="btn btn-primary sm-btn" name="add_med_row['.$medtime.']" value="Add Row" />
						<input type="submit" class="btn btn-primary sm-btn" name="remove_med_row['.$medtime.']" value="Remove Row" />
					</th>
				</tr>'."\r";
				 	
				echo '<tr class="subheading">'."\r"; 
					echo '<td style="width:50px;">&nbsp;</td>'."\r";	
					foreach($fields as $field):	
						echo '<td>'.$field.'</td>'."\r";	
					endforeach;   
				echo '</tr>'."\r";
				if(!empty($_SESSION['rowstoshow'][$medtime])):
					for($l=1;$l<=$_SESSION['rowstoshow'][$medtime];$l++):	
					
						
						$record_id = (!empty($data['medications'][$medtime]['record_id'][$l]) ? $data['medications'][$medtime]['record_id'][$l] : '');
						echo '<tr>'."\r"; 
						
							echo '<td style="width:50px;">'.$l.'&nbsp;<input type="hidden" name="'.$medtime.'[\'record_id\']['.$l.']" value="'.$record_id.'" /></td>'."\r";	
							foreach($fields as $field):
							
								$datavalue = (!empty($data['medications'][$medtime][$field][$l]) ? $data['medications'][$medtime][$field][$l] : '');
								$inputvalue = (!empty($_POST[$medtime][$field][$l]) ? $_POST[$medtime][$field][$l] : $datavalue); 
																
								echo '<td><input type="text" name="'.$medtime.'['.$field.']['.$l.']" value="'.$inputvalue.'" /></td>'."\r";	
							endforeach;	 
						echo '</tr>'."\r";			
					endfor;	  
				endif;	
				  
		endforeach;	
			echo '<tr>
				<th colspan="'.$cols.'">											   
					<input type="submit" class="btn btn-primary sm-btn right" name="savedata" value="Save">	
					<input type="submit" class="btn btn-primary sm-btn left" name="clear" value="Clear">
				</th>
			</tr>'."\r";	
		
		echo '</table> '."\r";
	echo '</div> '."\r";  
echo '</form> '."\r";
?>

I will attach my full sample should you wish to play with it to suit your needs.
testpost.php (11.6 KB)

2 Likes

It might be for some folk but I struggled to make it dynamic :slight_smile:

Many thanks for the detailed example!

I was amazed at the complexity of your excellent solution. It is remarkably detailed and does everything I want. The output medication chart, saving to a database table and some sort of user login is still required and should be straight forward.

I have uploaded a menu of links to the web pages which can be seen here

That’s great. I noticed that session is not holding the “rows to show” on the sample you have on the webpage. Was that intentional not using the session start? Just noting in processing you would Save or Update based on if the record_id input is empty or not.

I modified your script by adding a demo button and it created problems with sessions so removed un-linked the sessions.

I have just removed the un-link , uploaded and hopes it works for all.

index-drummin.zip (3.6 KB)

Correction: Just noting that the hidden input for record_id needs to have no quotes around the record_id key like so.

echo '<td style="width:50px;">'.$l.'&nbsp;<input type="hidden" name="'.$medtime.'[record_id]['.$l.']" value="'.$record_id.'" /></td>'."\r";	

Or you could define the field as a variable to use in the input. Either way there are no quotes around the key.

$record_field = "record_id";
echo '<td style="width:50px;">'.$l.'&nbsp;<input type="hidden" name="'.$medtime.'['.$record_field.']['.$l.']" value="'.$record_id.'" /></td>'."\r";	

Many thanks once again for the excellent script and the correction.

I prefer to use PHP Heredoc strings because it makes readability so much easier. Curly braces are only required around array variables and without any spaces.

Check the function used in index-004.php. The source is at the bottom of the page:

//=========================================================
function showMeds
(
    array $meds = []
)
: string // return type
{
    $result = '';
    foreach($meds as $key => $med) :
        $result .= <<< ______EOT
            <dl class="w88 mga">
                <dt> {$med[0]} </dt>
                <dd> {$med[2]} </dd>
                <dd> {$med[1]} </dd>
            </dl>    
______EOT;
    endforeach;

    return $result;
}///

Tapped on my tablet :frowning:

Edit:

Your script using PHP Heredoc :frowning:

// echo '<td style="width:50px;">'.$l.'&nbsp;<input type="hidden" name="'.$medtime.'['.$record_field.']['.$l.']" value="'.$record_id.'" /></td>'."\r";	

$result = <<< ____EOT
<td style="width:50px;">
 $i &nbsp; 
<input
  type="hidden"
  name="{$medtime[$record_field][$i]}
  value="$record_id" 
/>
</td>
\r 
____EOT;

Renamed and updated online web pages, added index-drummin-ver-002.php

Modifcations:

  1. corrected syntax error
  2. added “remove” single drug

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.