【问题标题】:I cant find the error in my code I always get insufficient funds我在代码中找不到错误 我总是资金不足
【发布时间】:2019-10-04 04:42:41
【问题描述】:

我设置了 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";
    }
?>

每次我尝试提款时,我都会收到“Insufficient Funds”,但那里有足够的资金。

【问题讨论】:

    标签: php sql pdo


    【解决方案1】:

    如果您的代码做了一些意想不到的事情,那么您很有可能在某个地方做出了假设。您可以在代码中确定的一件事是,如果它打印“资金不足”,那么它会看到 $wamount 的值大于或等于 $userVal['balance'] 的值。

    这可能是由于几个原因,包括余额不如您想象的那么多,或者很可能是存在某种强制或类型差异或不正确的字段映射。

    我的建议是在if 语句之前查看这些值。如果你有调试器并且知道如何使用它,那就去做吧。但如果您不这样做,您可以在 if 语句之前临时添加此代码。

    var_dump('Withdrawal amount', $wamount);
    var_dump('Balance', $userVal['balance']);
    

    这应该会产生一些输出,告诉您变量$wamount$userVal['balance'] 的值和类型。看看你得到的值。希望问题会很明显。如果不是,请特别注意变量的类型。如果它们不同,例如一个是字符串,另一个是浮点数或整数或其他内容,则 PHP 正在执行类型强制,并且可能存在您不知道的情况,这将导致看起来的值成为你所期望的,但实际上并非如此。

    【讨论】:

    • 当我测试 var_dump 我得到 string(17) "Withdrawal amount" string(2) "60" string(7) "Balance" NULL Insufficient Fund 但他们是两个 int 在我的数据库中(悲伤的脸)
    • @littlejamesc 在 PHPMyAdmin 中使用查询,看看你得到了什么结果。
    • @littlejamesc 这里有一些东西会让你更加悲伤。您刚刚完成了无休止的调试中的第一次迭代。现在您知道 $userVal['balance'] 为空,您必须找出原因。返回的值为 null 或整行不存在。现在是 var_dump 整个 $userVal 的时候了,然后进行相应的操作。
    • 如果 $userVal 包含其他信息但余额为空,那么无论您怎么想,它在您的数据库中都是空的。如果 $userVal 为假,则需要检查另一个假设,即 $_POST['email'] 包含在数据库中具有完全匹配的值。然后您将不得不检查有关 SQL、数据库等的其他假设。是的,调试占用了程序员的大部分时间。欢迎加入俱乐部。
    • 大家好,我最初将余额手动添加到 sql 表中。现在我尝试在代码中设置它:$userVal['balance'] = 1000。它工作并用余额更新了我的 sql 表 - 提取金额。然后我尝试在 sql 表上再次手动添加,一切正常。我仍然不能说 NULL 的初始错误来自哪里,但它现在似乎工作正常。谢谢大家
    【解决方案2】:

    我整理了一些测试表来模拟可以从上面推断出的结构(它可能与您的实际数据库架构不同)并通过上面的代码生成以下内容。这对我的测试有效。注意我添加了 PDO 事务语句,因为它在这种情况下看起来很合适。我发现的一个问题是隐藏字段中使用的日期格式 - 如果 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 );
    
    
    
            $balance = floatval( $rs->balance ) - floatval( $wamount );
    
    
    
            if( $balance < 0 ){
    
                /* Cannot withdraw more than is in the account - error */
                $db->rollback();
                $error='Error: Insufficient funds!';
    
            } else {
                $status=false;
    
    
    
                $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='client@example.com';
    
            /* 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>
    

    【讨论】:

      猜你喜欢
      • 2021-04-27
      • 1970-01-01
      • 1970-01-01
      • 2017-08-15
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多