我设置了3个sql表:'client''inv'和'wit'数据库连接可以正常工作,代码中的其他页面也可以,但是此特定页面存在问题。
我有一个页面new.php:
<?php session_start();
if(!isset($_SESSION["email"]))
{
header("location:../login.php");
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<?php include("header.php"); ?>
<form action="withdraw.php" method="post" class="m-form m-form--label-align-right m-form--fit" id="withdrawalForm">
<input type="hidden" name="email" value="<?php echo $userVal['email']; ?>" />
<input type="hidden" name="w_date" value="<?php echo date("d-m-Y"); ?>" />
<input type="hidden" name="w_status" value="Pending" />
<input type="hidden" name="balance" value="<?php echo $userVal['balance']; ?>" />
<input type="text" name="method" value="" />
<input type="text" name="balance" value="$<?php echo $userVal['balance']; ?>" disabled=true readonly />
<input type="number" name="w_amount" value="" placeholder="<?php echo $userVal['balance']; ?> or less" required />
<input type="text" name="wallet" value="" placeholder="Wallet Address" required />
<input type="submit" name="withdraw" value="withdraw" />
</body>
</html>
header.php具有:
<?php
include("pdoconnect.php");
$id = $_SESSION["email"];
$user = $pdotestconn->prepare("SELECT * FROM client JOIN inv ON client.email = inv.email WHERE client.email = :uname ");
$user->bindParam(":uname", $id);
$user->execute();
$userVal = $user->fetch(PDO::FETCH_ASSOC);
?>
然后我有了withdraw.php:
<?php
include("pdoconnect.php");
$datei=date("D M d, Y g:i a");
$email = $_POST['email'];
$wdate = $_POST['w_date'];
$method = $_POST['method'];
$wamount = $_POST['w_amount'];
$wstatus = $_POST['w_status'];
$wallet = $_POST['wallet'];
$user = $pdotestconn->prepare("SELECT * FROM client JOIN wit ON client.email = wit.email WHERE client.email = :uname ");
$user->bindParam(":uname", $email);
$user->execute();
$userVal = $user->fetch(PDO::FETCH_ASSOC);
if ($wamount >= $userVal['balance']) {
echo "Insufficient Fund";
} else {
$balance = $userVal['balance'] - $wamount;
$ins = $pdotestconn->prepare("INSERT INTO wit (email,w_date,method,w_amount,w_status,wallet) VALUES (:email,:w_date,:method,:w_amount,:w_status,:wallet)");
$ins->bindParam(":email", $email);
$ins->bindParam(":w_date", $wdate);
$ins->bindParam(":method", $method);
$ins->bindParam(":w_amount", $wamount);
$ins->bindParam(":w_status", $wstatus);
$ins->bindParam(":wallet", $wallet);
$ins->execute();
$up = $pdotestconn->prepare("UPDATE client SET balance = :credit WHERE email = :email ");
$up->bindParam(":credit", $balance);
$up->bindParam(":email", $email);
$up->execute();
echo "ok";
}
?>
每次尝试进行提款时,我都会收到“ 资金不足”,但那里有足够的资金。我需要帮助的人
如果您的代码做了意外的事情,则很有可能在某个地方进行假设。您可以确定的一件事是,如果代码中显示“资金不足”,则它会看到$wamount
的值大于或等于$userVal['balance']
的值。
这可能是出于两个原因,包括余额未达到您的预期,或者有可能出现某种强制性或类型差异或不正确的字段映射。
我的建议是在if
语句之前查看那些值。如果您有调试器并且知道如何使用它,请执行此操作。但是,如果您不这样做,则可以在if
语句之前临时添加此代码。
var_dump('Withdrawal amount', $wamount);
var_dump('Balance', $userVal['balance']);
这应该会产生一点输出,告诉您变量$wamount
和$userVal['balance']
的值以及类型。看一下您获得的值。希望问题会很明显。如果不是,请特别注意变量的类型。如果它们不同,例如其中一个是字符串,另一个是浮点数或int等,则PHP正在执行类型强制,并且可能会导致您不了解某些东西,而那会导致值看起来达到您的期望,但实际上不是。
希望这会有所帮助!
我整理了一些测试表,以模仿可以从上面推导出的结构(它可能与您的实际db模式不同),并通过上面的代码工作以产生以下内容。这对我的测试有效。注意,在这种情况下,我似乎添加了PDO Transaction语句。我发现的一个问题是隐藏字段中使用的日期格式-如果db表中的列是date
字段,则可能会导致错误,因此为什么更改了隐藏字段中的格式。
mysql> describe client;
+---------+------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| email | varchar(64) | NO | UNI | NULL | |
| balance | decimal(10,2) unsigned | NO | | NULL | |
+---------+------------------------+------+-----+---------+----------------+
mysql> describe wit;
+----------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| email | varchar(64) | NO | MUL | NULL | |
| w_date | date | NO | | NULL | |
| method | varchar(50) | NO | | NULL | |
| w_amount | decimal(10,2) | NO | | NULL | |
| w_status | varchar(50) | NO | | NULL | |
| wallet | varchar(255) | NO | | NULL | |
+----------+------------------+------+-----+---------+----------------+
mysql> describe inv;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| email | varchar(64) | NO | MUL | NULL | |
+-------+------------------+------+-----+---------+----------------+
脚本全部在一页上进行测试:
<?php
$error=false;
$message=false;
$dbport = 3306;
$dbhost = 'localhost';
$dbuser = 'root';
$dbpwd = 'xxx';
$dbname = 'xxx';
$options=array(
PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL,
PDO::ATTR_PERSISTENT => false,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
PDO::ATTR_EMULATE_PREPARES => true,
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'utf8mb4\' COLLATE \'utf8mb4_general_ci\', @@sql_mode = STRICT_ALL_TABLES, @@foreign_key_checks = 1'
);
$dsn='mysql:host='.$dbhost.';port='.$dbport.';dbname='.$dbname.';charset=utf8';
$db=new PDO( $dsn, $dbuser, $dbpwd, $options );
if( $_SERVER['REQUEST_METHOD']=='POST' && isset( $_POST['email'],$_POST['w_date'],$_POST['method'],$_POST['w_amount'],$_POST['w_status'],$_POST['wallet'] ) ){
#$datei=date("D M d, Y g:i a"); /* unused */
$email = $_POST['email'];
$wdate = $_POST['w_date'];
$method = $_POST['method'];
$wamount = $_POST['w_amount'];
$wstatus = $_POST['w_status'];
$wallet = $_POST['wallet'];
/* seems like an appropriate candidate for a `Transaction` !! */
$db->beginTransaction();
$sql='select * from `client` join `wit` on client.email = wit.email where client.email = :uname';
$stmt=$db->prepare( $sql );
$args=array(
':uname' => $email
);
$stmt->execute( $args );
$rs=$stmt->fetch( PDO::FETCH_OBJ );
if( floatval( $wamount ) >= floatval( $rs->balance ) ){
/* Cannot withdraw more than is in the account - error */
$db->rollback();
$error='Error: Insufficient funds!';
} else {
$status=false;
$balance = floatval( $rs->balance ) - floatval( $wamount );
$sql='insert into `wit` ( `email`, `w_date`, `method`, `w_amount`, `w_status`, `wallet` ) values ( :email, :date, :method, :amount, :status, :wallet )';
$stmt=$db->prepare( $sql );
$args=array(
':email' => $email,
':date' => $wdate,
':method' => $method,
':amount' => $wamount,
':status' => $wstatus,
':wallet' => $wallet
);
$res=$stmt->execute( $args );
if( $res ){
$sql='update `client` set `balance`=:balance where `email`=:email';
$stmt=$db->prepare( $sql );
$args=array(
':balance' => $balance,
':email' => $email
);
$status=$stmt->execute( $args );
}
if( $status ){
$db->commit();
$message=sprintf('Congratulations! You have successfully transferred %s', floatval( $wamount ) );
} else {
$message=sprintf('Sorry, there was a problem transferring %s', floatval( $wamount ) );
}
}
}
?>
<!DOCTYPE html>
<html lang='en'>
<head>
<title>Money money money</title>
<style>
.error{color:red}
.status{color:green}
</style>
</head>
<body>
<?php
/* to emulate header.php */
$sql='select * from `client` join inv on client.email = inv.email where client.email = :uname';
$stmt=$db->prepare( $sql );
/* Rather than a session, to test a statically declared email will suffice */
$id='[email protected]';
/* In practice you will use $_SESSION['email'] here */
$args=array(
':uname' => $id
);
$res=$stmt->execute( $args );
$userVal=$stmt->fetch( PDO::FETCH_BOTH );
?>
<form method='post'><!-- POST to same page for testing -->
<?php
if( $error )printf( '<h1 class="error">%s</h1>', $error );
if( $message )printf( '<h1 class="status">%s</h1>', $message );
?>
<input type='hidden' name='email' value='<?php echo $userVal['email']; ?>' />
<input type='hidden' name='w_date' value='<?php echo date('Y-m-d'); ?>' /><!-- incorrect date format for DB -->
<input type='hidden' name='w_status' value='Pending' />
<input type='hidden' name='balance' value='<?php echo $userVal['balance']; ?>' />
<input type='text' name='method' value='' placeholder='Method' />
<input type='text' name='balance' value='$<?php echo $userVal['balance']; ?>' disabled=true readonly />
<input type='number' name='w_amount' value='' placeholder='<?php echo $userVal['balance']; ?> or less' required />
<input type='text' name='wallet' value='' placeholder='Wallet Address' required />
<input type='submit' name='withdraw' value='Withdraw' />
</form>
</body>
</html>