Логика такая: выводится текст из базы, рядом есть поле для ввода, после ввода текста и нажатия на ссылку "редактировать" запись в базе должна измениться. Я сделал это, только если текст статичен. Все работает. Но мне нужно взять текст из ввода. Как мне это сделать? Не могли бы вы мне помочь?
Я добавил «скрытый ввод», потому что видел аналогичные решения с ним, но не могу получить значения.
<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>
стена.php:
if (isset($_GET['ed'])) {
$id = $_GET['ed'];
mysqli_query($connect, "UPDATE message SET message = 'ffffdf' WHERE id = $id");
header('Location: ../profile.php');
}
Но я сделал ту же кнопку удаления с помощью GET-запросов и в таком виде все заработало. Я хочу использовать здесь как POST, так и GET. Разве я не могу сделать это таким образом?
Лучше быть последовательным. Лучше установить оба как POST. С другой стороны, попробуйте использовать подготовленный оператор в обновлении БД. Похоже, вы используете цикл для получения данных из нескольких записей. Пожалуйста, используйте AJAX в вашем случае
Вы генерируете HTML в цикле — будет ли сгенерировано более 1 div.content
? Если да, у вас есть другие проблемы
Используйте GET
для получения данных и POST
для обновления записей — обычно это считается практикой.
Да, будет больше 1.
Не могли бы вы показать мне примерно, как здесь должен выглядеть запрос GET?
Я неправильно прочитал html - подумал, что есть дубликаты идентификаторов - игнорируйте предыдущий комментарий о других проблемах.
Но все равно будут проблемы из-за повторяющихся имен. Имена должны быть уникальными, как и идентификаторы. Вам лучше создать целую форму для каждого из ваших элементов. Используйте post
и замените эту ссылку кнопкой отправки.
Я изменил ваш код, надеюсь, это даст то, что вы хотите:
ОБНОВЛЕНИЕ: я уменьшаю область формы и создаю несколько форм для каждой строки и добавляю идентификатор строки ко всем элементам формы, и это работает для меня.
<?php foreach($check_message as $row): ?>
<div class = "content">
<form class = "msg-wall" method = "post" action = "#" id = "form_<?= $row['id'] ?>">
<p class = "msg"><?= $row['message'] ?></p>
<input type = "text" name = "new_message_<?= $row['id'] ?>" form = "form_<?= $row['id'] ?>">
<input type = "hidden" name = "id" value = "<?= $row['id'] ?>" form = "form_<?= $row['id'] ?>">
<input type = "submit" value = "Edit" form = "form_<?= $row['id'] ?>"/>
</form>
</div>
<?php endforeach; ?>`
стена.php:
if (isset($_POST['id']) && isset($_POST["new_message_" . $_POST['id']])) {
$id = $_POST['id'];
$new_message = $_POST['new_message_' . $_POST['id']];
mysqli_query($connect, "UPDATE message SET message = $new_message WHERE id = $id");
header('Location: ../profile.php');
}
Ничего не изменилось, когда я ввел текст во ввод и нажал кнопку (
Нет необходимости добавлять идентификатор к другим входным именам, если вы создаете новую форму с каждой итерацией. Это только усложнит обработку подачи. Кроме того, это все еще остается открытым для SQL-инъекций.
@El_Vanja Я думаю, это упростит обработку отправки, потому что этот php обрабатывает все запросы нескольких пользователей (что может произойти одновременно). Если я отправляю только идентификатор со скрытыми элементами, последнее значение new_message перезаписывает поля new_message других пользователей.
Нет. Каждый запрос пользователя обрабатывается индивидуально. Моя подача той же формы не имеет ничего общего с вашей подачей той же формы. И нет никакого способа, которым один пользователь может отправить несколько правок, когда у вас есть отдельные формы.
Использование GET
для обновления записей в базе данных не является хорошей идеей. Запрос GET можно легко изменить, чтобы повлиять на другие записи, его можно добавить в закладки, поделиться им и т. д. Общепринятым методом обновления записей является использование POST
, которое теоретически можно использовать в сочетании с GET, если действительно важно передавать переменные таким образом (например, изменение действия формы).
Исходный код уязвим для SQL-инъекций, поэтому, когда эта уязвимость существует в сочетании с запросами GET, вы недалеки от проблем. Следующие попытки снижают риски с помощью POST в сочетании с «Подготовленными заявлениями» — комментарии, сделанные в коде, должны дать дополнительную информацию.
<?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>
Ваша форма настроена на нас
POST
, но ваш уязвимый PHP/SQL используетGET