Я просто самообучающийся PHP и SQL. Этот вопрос кажется повторяющимся, но я не могу найти точное решение для моей проблемы.
У меня есть база данных SQL для управления запасами мобильных телефонов. Я реализовал PHP-скрипт для отображения содержимого базы данных в таблице. Мне нужно дополнительно улучшить скрипт, чтобы пользователь мог изменить состояние мобильного телефона, например, Работает или Не работает. Для этого я создал другую базу данных SQL, хранящую эту информацию. Я могу отобразить детали в раскрывающемся списке, но когда я переключаюсь с " Работает" на " Не работает" и нажимаю кнопку " Отправить", никаких изменений не происходит в базе данных, а также на веб-сервере.
<?php
$servername="localhost";
$username="root";
$password="XXXXX";
$dbname="inventory_db";
//Connection
$conn =mysqli_connect($servername,$username,$password);
$db_handle = $conn->select_db($dbname);
//Connection check
if($conn->connect_error)
{
die("Connection failed:" .$conn->connect_error);
}
else {
echo "connection setup";
}
if($db_handle)
{
$sql="SELECT asset_no,asset_name,current_holder,location,status FROM Phone_table ";
$sql_status="SELECT idstatus,status_name FROM status_table";
?>
<!DOCTYPE html>
<HTML>
<HEAD>
<STYLE>
.asset_table
{
width: 100%;
border :1px solid black;
}
td{
text-align: left;
padding: 15px;
border: 1px solid black;
}
th{
border: 1px solid black;
}
</STYLE>
</HEAD>
<BODY>
<form method="post">
<TABLE class="asset_table">
<TR>
<TH>Asset Number</TH>
<TH>Asset Name</TH>
<TH>Asset Holder</TH>
<TH>Location</TH>
<TH>Status</TH>
</TR>
<?php
$result=$conn->query($sql);
$count=mysqli_num_rows($result);
if($result->num_rows > 0)
{
while($row=$result->fetch_assoc())
{?>
<TR>
<TD> <?php echo $row['asset_no']; ?> </TD>
<TD> <?php echo $row['asset_name']; ?></TD>
<TD> <?php echo $row['current_holder']; ?></TD>
<TD> <?php echo $row['location']; ?></TD>
<TD><select>
<?php
<!-- *****This is where I am stuck*****-->
$result_status=$conn->query($sql_status);
if($result_status->num_rows > 0)
{
while($row_status=$result_status->fetch_assoc())
{ ?>
<option value =' <?php echo $row_status['idstatus']?> '>
<?php echo $row_status['status_name'];?> </option>
<?php $row['status']=$row_status['status_name'];
}} ?></select>
</TD>
</TR>
<?php
}}?>
<input type="submit">
</form>
<?php
if($submit)
{
for($i=0;$i<$count;$i++)
{
$sql="UPDATE Phone_table SET status='$status[$i]' WHERE asset_no='$asset_no[$i]'";
$result=$conn->query($sql);
}
}
?>
</TABLE>
</BODY>
</HTML>
<?php }
ob_end_flush(); ?>
Одна проблема с существующим кодом состоит в том, что не было никакого способа связать представленное значение для статуса актива (даже если ему было дано имя!) С конкретной записью в базе данных. Оператору update обычно требуется идентификатор в предложении where
, чтобы соответствующая запись могла быть обновлена, а ВСЕ записи обновляются одинаково. Для этого, учитывая структуру HTML и общий подход (без javascript и единой формы), использование скрытого поля ввода для каждой строки в таблице для хранения идентификатора записи, кажется, имеет смысл. Когда форма отправлена, значение для меню select
и идентификатор должны быть связаны - вы увидите демонстрацию ниже.
Поскольку существует одна форма с несколькими записями, меню select
и hidden
ввод должны обрабатываться как массивы, то есть их имена должны иметь name[]
формы name[]
Еще одна вещь, на которую стоит обратить внимание, это использование переменных непосредственно в SQL. Эта практика делает ваш код уязвимым для SQL-инъекций, и хотя это может быть в закрытой системе где-то с доверенными пользователями и т.д., Вы никогда не знаете, что может произойти!
<?php
error_reporting( E_ALL );
ini_set( 'display_errors', 1 );
/* connect to the db */
$dbhost = 'localhost';
$dbuser = 'root';
$dbpwd = 'xxx';
$dbname = 'inventory_db';
$db = new mysqli( $dbhost, $dbuser, $dbpwd, $dbname );
/* declare the sql statements for later use */
$sql=(object)array(
'phones' => 'select 'asset_no', 'asset_name', 'current_holder', 'location', 'status' from 'phone_table'',
'status' => 'select 'idstatus', 'status_name' from 'status_table'',
'update' => 'update 'phone_table' set 'status'=? where asset_no=?'
);
/* very basic utility function to generate select menu */
function createselect( $name, $data, $value ){
$html=array();
$html[]=sprintf( '<select name="%s">', $name );
foreach( $data as $id => $status ){
$selected = $id == $value ? ' selected=true' : '';
$html[]=sprintf('<option value="%s"%s>%s', $id, $selected, $status );
}
$html[]='</select>';
return implode( PHP_EOL, $html );
}
/* query database to get possible status values which are used to create the SELECT menus */
$status=array();
$results=$db->query( $sql->status );
if( $results ){
while( $rs=$results->fetch_object() )$status[ $rs->idstatus ]=$rs->status_name;
}
if( $_SERVER['REQUEST_METHOD']=='POST' ){
ob_clean();
/* using 'user supplied data' - use a prepared statement to be safe! */
$stmt=$db->prepare( $sql->update );
$stmt->bind_param( 'ii', $assetstatus, $assetid );
/* Perform the update */
foreach( $_POST['id'] as $i => $assetid ){
$assetstatus = $_POST['status'][ $i ];
$stmt->execute();
}
$stmt->close();
exit( header( 'Location: ?db=updated' ) );
}
?>
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>Asses or Assets?</title>
<style>
body{font-family:verdana}
table{ width: 100%; border :1px solid black; }
td{ text-align: left; padding: 15px; border: 1px solid black;text-align:center; }
th{ border: 1px solid black; }
input,select{padding:1rem;width:100%}
</style>
</head>
<body>
<?php
/* get the phones... no user input so no need for prepared statement */
$results = $db->query( $sql->phones );
if( $results ){
?>
<form method='post'>
<table>
<thead>
<tr>
<th>Asset Number</th>
<th>Asset Name</th>
<th>Asset Holder</th>
<th>Location</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<?php
while( $rs = $results->fetch_object() ){
printf(
"<tr>
<td>%s<input type='hidden' name='id[]' value='%d' /></td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
</tr>",
$rs->asset_no,
$rs->asset_no,
$rs->asset_name,
$rs->current_holder,
$rs->location,
createselect( 'status[]', $status, $rs->status )
);
}
?>
</tbody>
<tfoot>
<tr>
<td colspan=5>
<input type='submit' />
</td>
</tr>
</tfoot>
</table>
</form>
<?php
}//close 'if'
?>
</body>
</html>
В общем случае создание/отображение формы и воздействие на отправленную форму - это два совершенно не связанных HTTP-запроса.
Вы должны изменить несколько вещей, чтобы ваш скрипт работал:
1. Добавьте скрытое поле для каждого номера актива:
<TD>
<input type="hidden" name="asset_no[]" value="<?php echo $row['asset_no']; ?>">
<?php echo $row['asset_no']; ?>
</TD>
2. Добавьте атрибут name в выбранные вами поля:
<TD><select name="asset_status[]">
3. Сделайте так, чтобы ваши выбранные поля предварительно выбирали текущий статус и удаляли пробелы в значении:
<option value ='<?php echo $row_status['idstatus'] ?>' <?= $row['status'] == $row_status['idstatus'] ? ' selected' : '' ?>>
4. Удалите этот оператор, поскольку он ничего не делает (вы не записываете в массив, который вы читаете из базы данных):
$row['status']=$row_status['status_name'];
5. Добавьте свойство name в поле отправки:
<input type="submit" name="submit">
6. Считайте отправленную форму из суперглобального массива $_POST
(см. Php.net):
if(isset($_POST['submit']))
{
for($i=0;$i<count($_POST['asset_no']);$i++)
{
$asset_status = mysqli_real_escape_string($conn, $_POST['asset_status'][$i]);
$asset_no = mysqli_real_escape_string($conn, $_POST['asset_no'][$i]);
$sql = "UPDATE Phone_table SET status='$asset_status' WHERE asset_no='$asset_no'";
$result = $conn->query($sql);
}
}
1. Дайте имя вашему input
<input type="submit" name="submit">
2. Дайте автоматически увеличенные уникальные имена в поле select
<select name="your_unique_name">
3. Предоставьте скрытое текстовое поле ввода для помещения asset_no
в число отображаемых номеров активов.
4.Проверьте, если этот вход нажал
if(isset($_POST["submit"]))
{
for($i=0;$i<$count;$i++)
{ $status= //catch it from posted form
$asset_no= //catch it from posted form
$sql="UPDATE Phone_table SET status='$status' WHERE
asset_no='$asset_no'";
$result=$conn->query($sql);
}
}