Home > Software engineering >  PHP: how to pass a variable as a multidimensional array with method=POST
PHP: how to pass a variable as a multidimensional array with method=POST

Time:12-06

I have a PHP script that allows end-users, using a dynamic form, to select how many entry he/she needs. 1 set of data is 3 entries. Each entry will contain its own field. For example, if he/she needs 4 set of data, the end-user will select 4 in a drop down list and the PHP script will dynamically display a blank form with 4 lines, each line containing 3 fields (so, a 4x3 matrix, with 12 fields).

Then the script has to write the data collected from the 12 field into a text file. I am struggling to pass the data collected in the form, to the PHP script that will actually write into the txt file.

Here is the main page: MAIN.php:

<?php
$Matrix = array(array());
$data = $name*3;                    //1 line entry contains 3 columns of data; total $name line entry
$block=null;
$entry=null;
for ($n = 0; $n <= $data-1; $n =1) {
    $block=fmod($n,$name);
    $entry=($n-$block)/$name;
    $block=$block 1;                //line   (horizontal)
    $entry=$entry 1;                //column (vertical); 3 in this case
}
for ($a = 0; $a <= $block-1; $a =1) {                  //line   (horizontal)
    for ($b = 0; $b <= $entry-1; $b =1) {            //column (vertical)
        $Matrix[$a][$b]=null;
    }
}
echo '
<form action="WSCRIPT.php" method="POST">
    <table style="width:40%">
        <col style="width:5%">
        <col style="width:20%">
        <col style="width:10%">
        <col style="width:10%">
      <tr>
        <td><center>#</center></td>
        <td><center>Item / Description</center></td>
        <td><center>Start date</center></td>
        <td><center>End date</center></td>
      </tr>';
echo '<tr>';
for ($a = 0; $a <= $block-1; $a =1) {                  //line   (horizontal)
    $line=$a 1;
    echo '<td><center>'.$line.'</center></td>';
    for ($b = 0; $b <= $entry-1; $b =1) {            //column (vertical)
        echo '<td><center><input name="'.$Matrix[$a][$b].'" type="text" /></center></td>';
    }
    echo '</tr>';
}
echo '
    </table>
    <br>
    <input type="submit" name="submit" value="Save Data">
</form>';
?>

And the PHP script writing to the txt file, WSCRIPT.php:

<?php
$block = 10; //max
$entry = 3;  //constant
for ($a = 0; $a <= $block-1; $a =1) {                //line   (horizontal)
    for ($b = 0; $b <= $entry-1; $b =1) {            //column (vertical)
        $data = $_POST['.$Matrix['.$a.']['.$b.'].'] . "\r\n";
        $ret = file_put_contents('WSCRIPT.txt', $data, FILE_APPEND | LOCK_EX);
        if($ret === false) {
            die('Error writing this file');
        }
        else {
            echo "$ret bytes written to file";
        }
    }
}
?>

The error I'm having is showing up as:

Notice: Undefined index: .$Matrix[0][0]. in C:\TEST\WSCRIPT.php on line 9
Notice: Undefined index: .$Matrix[0][1]. in C:\TEST\WSCRIPT.php on line 9
Notice: Undefined index: .$Matrix[0][2]. in C:\TEST\WSCRIPT.php on line 9
Notice: Undefined index: .$Matrix[1][0]. in C:\TEST\WSCRIPT.php on line 9
etc...

where line 9 is the line from the WSCRIPT.php, with:

$data = $_POST['.$Matrix['.$a.']['.$b.'].'] . "\r\n";

Can anybody point me in the right direction on how to move forward... I'm a PHP beginner and self-learning on the go...

Thank you very much!

Julien

CodePudding user response:

Naming a form input element $Matrix = array(array()); is not the correct approach. The element should have a proper name that uses the array syntax, such as banana[] etc so that name becomes available within the POSTed data.

I put together a single page demo to illustrate how one might accomplish the goal of writing to textfile the data collected from a dynamically generated form where the names of individual text fields use a common name with an array syntax. As the code above does not show the select menu used to create the initial display I used some javascript and a template for content as you'll see below.

<?php
    
    error_reporting( E_ALL );
    
    if( $_SERVER['REQUEST_METHOD']=='POST' && isset( $_POST['matrix'] ) ){
        /**************************
            WSCRIPT.php emulator
        */
        /* Split the matrix data into chunks of 3 ( 3 inputs per table row! ) */
        $chunks=array_chunk( $_POST['matrix'], 3 );
        
        
        $file='wscript.txt';
        @unlink( $file );
        
        
        
        foreach( $chunks as $trio ){
            /* 
                Each row as shown in the HTML table will be written to it's own line in the text file.
                The individual values are separated with the pipe character here - but could obviously be
                formatted completely differently.
            */
            file_put_contents( $file, implode( ' | ', $trio ) . PHP_EOL, FILE_APPEND | LOCK_EX );
        }
        
        exit( sprintf( '%s bytes written to file',filesize( $file ) ) );
    }
?>
<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title>write dynamically generated form element content to text file</title>
        <style>
            :root{ counter-reset:rows; }
            tbody tr{ counter-increment:rows; }
            tr td:first-of-type:before{ content:counter(rows) }
        </style>
    </head>
    <body>
        
        <!--
            dropdown to select the number of rows the user
            wishes to add to the table. 
            
            Data added by javascript.
        -->
        <select name='qty'>
            <option selected hidden disabled>Please select
        </select>
        
        <!-- 
        
            action='WSCRIPT.php'
            
            ~ removed for single page demo where 
              php acts as wscript.php
        -->
        <form method='POST'>
            <table>
                <colgroup>
                    <col style='width:5%'>
                    <col style='width:20%'>
                    <col style='width:10%'>
                    <col style='width:10%'>
                </colgroup>
                <thead>
                    <tr>
                        <th>#</th>
                        <th>Item / Description</th>
                        <th>Start date</th>
                        <th>End date</th>
                    </tr>
                </thead>
                <tbody>
                <!-- dynamic content added here -->
                </tbody>
            </table>
            <input type='submit' value='Save Data' />
        </form>
        
        <!-- 
            a simple template holding the new table row and 3 input fields
            to be added in whatever quantity is selected from the dropdown.
            
            The name of the element uses the array syntax but importantly 
            it is a proper name rather than a PHP reference to an array!
            
            The name `matrix` will appear in the POST array when the form
            is submitted after the user has added whatever content they 
            need to.
        -->
        <template>
            <tr>
                <td>&nbsp;</td>
                <td><input type='text' name='matrix[]' /></td>
                <td><input type='text' name='matrix[]' /></td>
                <td><input type='text' name='matrix[]' /></td>
            </tr>
        </template>
        
        <script>
        
            let oSel=document.querySelector('select[name="qty"]');
            let tbl=document.querySelector('form > table > tbody');
            let tmpl=document.querySelector('template');
            
            /* add new options to the select menu */
            for( let i=1; i <=25; i   )oSel.append(new Option(i,i));
            
            /* add the event listener that clones the template N times and adds to the table */
            oSel.addEventListener('change',function(e){
                tbl.innerHTML='';
                
                for( let i=0; i < this.value; i   ){
                    let tr=tmpl.content.cloneNode( true );
                    tbl.append( tr );
                    
                    
                    
                    /**********************************************
                        add some junk data to each input element
                        - only because I'm lazy
                    */
                    document.querySelectorAll('td input').forEach((n,j)=>{
                        n.value=[
                            `cell:${j 1}`,
                            window.URL.createObjectURL(new Blob([])).split('/').pop().substr(0,16)
                        ].join( ' ' );
                    })
                }
            })
        </script>
    </body>
</html>
  • Related