Skip to content
Advertisement

How do I change a database entry when I enter text into an input?

The logic is this: the text is displayed from the database, next to it there is a box to enter, after you enter text and click on the link ‘edit’ record in the database should change. I did it only if the text is static. Everything works. But I need to take text from input. How do I do that? Can you please help me?

I added the ‘hidden input’ because I’ve seen similar solutions with it, but I can’t get the values.

<form class="msg-wall" method="post" action="/vendor/wall.php">
        <?php foreach($check_message as $row) { ?>
            <div class="content">
                <p class="msg"><?= $row['message'] ?></p>
                <input type="text" name="edit">
                <input type="hidden" name="id" value="<?= $row['id'] ?>">
                <a href="?ed=<?= $row['id'] ?>">edit</a>
            </div>
        <?php } ?>

</form>

wall.php:

if (isset($_GET['ed'])) {
    $id = $_GET['ed'];
    mysqli_query($connect, "UPDATE message SET message = 'ffffdf' WHERE id = $id");
    header('Location: ../profile.php');
}

Advertisement

Answer

Using GET to update records in a db is not a good idea. A GET request can easily be modified to affect other records, it can be bookmarked, shared and more. The generally accepted method for updating records is to use POST – which can, in theory, be used in conjunction with GET if it is really important to pass variables that way(such as modifying the form action)

The original code is vulnerable to SQL injection so when that vulnerability exists in conjunction with GET requests you are not far from problems. The following tries to mitigate risks by using POST in combination with “Prepared Statements” – the comments made through the code should offer further insight

<?php
    error_reporting( E_ALL );
    
    #db connect
    $dbhost =   'localhost';
    $dbuser =   'xxx'; 
    $dbpwd  =   'xxx'; 
    $dbname =   'xxx';
    
    try{
        mysqli_report( MYSQLI_REPORT_STRICT );
        $connect=new mysqli( $dbhost, $dbuser, $dbpwd, $dbname );
    }catch( Exception $e ){
        echo 'boom!';
    }
    
    
    if( $_SERVER['REQUEST_METHOD']=='POST' && isset( $_POST['ed'], $_POST['edit'] ) ){
        # generate basic update statement with suitable placeholders
        $sql='update `message` set `message` = ? where id = ?';
        
        # create the "Prepared Statement" object
        $stmt=$connect->prepare( $sql );
        
        # bind the placeholders to variables ( these do not need to be defined at this stage with mysqli )
        $stmt->bind_param('si', $edit, $ed );
        
        # assign variables
        $edit=$_POST['edit'];
        $ed=$_POST['ed'];
        
        # commit the statement
        $stmt->execute();
        $stmt->close();
        
        # go to the winchester and have a nice cold pint
        exit( header( 'Location: ../profile.php' ) );
    }
?>
<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title>Message Wall</title>
        <style>
            form textarea{
                border:none;
                background:whitesmoke;
                width:80%;
                height:5rem;
            }
            .content{
                width:50%;
                border-bottom:1px dotted grey;
                margin:0 0 2rem 0;
                padding:0 0 2rem 0;
            }
        </style>
    </head>
    <body>
    
        <!--
            not disclosed - the process by which the recordset / array is generated... so assumed below
            
            A single form with multiple input elements of the same name needs "Javascript"
            to aid the distinction of which records to update. The recordset is assumed to be a 
            multidimensional array created by iterating through a db query recordset.
            
            Using hidden inputs for both the message to write to db and the ID we can target
            these using "Javascript" prior to submitting the form.
        -->
        <?php
        
            # assumed method for generating recordset
            if( $_SERVER['REQUEST_METHOD']=='GET' ){
                $sql='select * from message';
                $res=$connect->query($sql);
                $check_message=array();
                while( $rs=$res->fetch_assoc() )$check_message[]=$rs;
            }
        
        ?>
        <form class='msg-wall' method='post' action='/vendor/wall.php'>
            <?php 
                foreach( $check_message as $row ) { 
            ?>
                <div class='content'>
                    <!-- original message -->
                    <p class='msg'><?= $row['message'] ?></p>
                    
                    <!-- a Copy of original message - field will be cleared when clicked -->
                    <textarea name='edit'><?= $row['message'] ?></textarea>
                    
                    <!-- rather than a hyperlink, a button makes sense -->
                    <button type='button' data-id='<?= $row['id'];?>'>Edit</button>
                </div>
            <?php 
                } 
            ?>
            <!-- these will be updated by js prior to submission -->
            <input type='hidden' name='edit' />
            <input type='hidden' name='ed' />
        </form>
        <script>
            const form=document.querySelector('form.msg-wall');
            // for each "button" - add an event listener to watch for "click" events
            form.querySelectorAll('div.content button').forEach( bttn => {
                bttn.onclick=function(e){
                    // update the two hidden elements
                    form.querySelector('input[type="hidden"][name="edit"]').value=this.parentNode.querySelector('textarea').value;
                    form.querySelector('input[type="hidden"][name="ed"]').value=this.dataset.id;
                    
                    // for convenience in testing THIS script, the "action" attribute needs to be the SAME page... this does NOT need to be used in final version
                    form.action=location.href;
                    
                    // submit the form
                    form.submit();
                };
            });
            
            // clear the textarea if clicked but restore the value if unchanged
            form.querySelectorAll('textarea[name="edit"]').forEach( n=>{
                n.onclick=function(e){ if( this.value==this.defaultValue )this.value=''; };
                n.onblur=function(e){ if( this.value=='' )this.value=this.defaultValue; };
            })
        </script>
    </body>
</html>
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement