There was such a problem, there is a transfer function on the site, but I can transfer the balance to any person except myself by typing any amount absolutely, it will go to me in a minus, and the person to whom I send it comes. How to make it so that the balance is checked, and if it is less than the amount claimed or less than zero, then an error has come out that this cannot be done, or if the balance is greater than or equal to the amount to be transferred, then it would be successfully transferred. Here is the code:

if($row['login'] != $nick) { $fa = 'error'; $error = 'Пользователь не найден'; }else { if($rowa['login'] == $nick){ $fa = 'error'; $error = 'Вы не можете перевести самому себе'; }else { if(!preg_match("/^[0-9]+$/", $summa)){ $fa = 'error'; $error = 'Сумма заполнено неверно'; }else { if($summa < 10) { $fa = 'error'; $error = 'Минимальная сумма перевода 10 '.$walletsite.''; }else { $update_sql = "Update ".$prefix."_users set balance=balance + '$summa' WHERE login='$nick'"; mysql_query($update_sql) or die("" . mysql_error()); $update_sql = "Update ".$prefix."_users set balance=balance - '$summa' WHERE hash='$sid'"; mysql_query($update_sql) or die("" . mysql_error()); $fa = 'success'; $error = 'Вы перевели '.$summa.' '.$walletsite.' пользователю '.$nick.''; $sql_selects = "SELECT * FROM ".$prefix."_users WHERE hash='$sid'"; $results = mysql_query($sql_selects); $rows = mysql_fetch_array($results); $new_balance = $rows['balance']; } } } } 
  • How to do? Get your balance from the table and compare with the amount of transfer. - u_mulder Nov.

2 answers 2

Without going into details of the other checks, the money transfer unit might look something like this (the code was not checked, as-is performance is not guaranteed):

 function do_update($update_sql) { mysql_query($update_sql) or throw new Exception(mysql_error()); return mysql_affected_rows(); // Возвращаем количество реально измененных строк } ... $Ok=0; try { mysql_query("START TRANSACTION"); // Начинаем транзакцию, которая будет выполнена вся целиком или ничего из нее $ret=do_update("Update " . $prefix . "_users set balance=balance - $summa WHERE hash='$sid' AND balance - $summa >= 0"); // Если денег не хватит, то запрос ничего не изменит и вернет 0 измененных строк if($ret != 1) throw new Exception("Недостаточно средств"); $ret=do_update("Update " . $prefix . "_users set balance=balance + $summa WHERE login='$nick'"); if($ret != 1) throw new Exception("Получатель средств не найден"); $Ok=1; } catch (Exception $e) { echo 'Произошла ошибка при переводе: ', $e->getMessage(); } finally { mysql_query($Ok ? "COMMIT" : "ROLLBACK"); // Завершаем или откатываем транзакцию в зависимости от успешного завершения запроса } 

In addition, I note that substituting the text of variables directly into the text of the query is related to the mass of potential errors and possibilities of SQL injection. In addition, the mysql_ extension has long been outdated and is already beginning to disappear from hosting with new versions of php. I strongly recommend switching to the use of PDO and prepared expressions with parameter binding .

     if ($row['login'] != $nick) { $fa = 'error'; $error = 'Пользователь не найден'; } else { if ($rowa['login'] == $nick) { $fa = 'error'; $error = 'Вы не можете перевести самому себе'; } else { if (!preg_match("/^[0-9]+$/", $summa)) { $fa = 'error'; $error = 'Сумма заполнено неверно'; } else { if ($summa < 10) { $fa = 'error'; $error = 'Минимальная сумма перевода 10 ' . $walletsite . ''; } else { $s1 = "SELECT * FROM " . $prefix . "_users WHERE hash='$sid'"; $r1 = mysql_query($s1); $rows = mysql_fetch_array($r1); $my_balance = $rows['balance']; if ($my_balance < $summa) { $fa = 'error'; $error = 'У вас нету столько'; } else { $update_sql = "Update " . $prefix . "_users set balance=balance + '$summa' WHERE login='$nick'"; mysql_query($update_sql) or die("" . mysql_error()); $update_sql = "Update " . $prefix . "_users set balance=balance - '$summa' WHERE hash='$sid'"; mysql_query($update_sql) or die("" . mysql_error()); $fa = 'success'; $error = 'Вы перевели ' . $summa . ' ' . $walletsite . ' пользователю ' . $nick . ''; $sql_selects = "SELECT * FROM " . $prefix . "_users WHERE hash='$sid'"; $results = mysql_query($sql_selects); $rows = mysql_fetch_array($results); $new_balance = $rows['balance']; } } } } } 
    • So you can not do, especially with money. At a minimum, you must enable transaction support on the connection (or enable one operation using start transaction ) and read the current balance using select for update so that the database record is locked during the balance check. Otherwise, the user having performed several operations at the same time can achieve the situation that you read one balance, but it changed before you gave the update. And he will go to minus. - Mike
    • In addition, when working outside of a transaction, there is a possibility that something will happen to mysql between the first and second update. And you write off the money, but you can not enroll! - Mike
    • Plus, there is no check for the existence of the user who is transferring. so you can easily transfer money to nowhere - Mike
    • Total: I suggest to begin transaction. make update set balance=balance - '$summa' WHERE hash='$sid' and balance - '$summa' > 0 (so that nothing could make the account negative). check not only for errors, but also for exactly 1 line changed (see mysql_affected_rows() ). Transfer money to the account of the second user. Make sure that again exactly one line is modified. If everything went well, give commit. If anything went wrong - rollback. Well, it would not hurt to check $ summ and $ nick for validity so that it would not create a SQL injection - Mike
    • But how to do it? - DrinkWithMe