0

I have a problem when comparing two PHP values. The first value is being passed as a parameter in the query string, while the second parameter is a result of an sql query.

The logic I need here is to compare both values, so that if the user has enough credit, his payment can be processed, but otherwise, an error message is shown.

This is my code:

public function storeNewTicket($userId, $amount, $validity) {

        $currentBalance = $this->getBalance($userId);
        $floatCurrentBalance = floatval($currentBalance);
        $floatAmount = floatval($amount);


        if ($floatCurrentBalance > $floatAmount) {

            /*Proceed with the insert*/
        }
        else {
            echo "You don't have enough credit to process this payment."
        }
    }

In a seperate function in the same file called getBalance(), I am getting the current balance of the user from a different table and returning it as an object. I am 100% sure that this is working. Here is the code:

public function getBalance($userId) {

    $stmt = $this->conn->prepare("SELECT balance FROM userbank WHERE UserId = ?");    
    $stmt->bind_param("s", $userId);

    if ($stmt->execute()) {
        $bal = $stmt->get_result()->fetch_assoc();
        $stmt->close();
        return $bal['balance'];
    } else {
        return NULL;
    }
}

The code is always going through the else clause and echoing: You don't have enough credit to process this payment.;

Can someone please help me understand how to convert the variables to decimals or floats and compare them?

Michele La Ferla
  • 6,775
  • 11
  • 53
  • 79
  • and what values do you get in the `storeNewTicket` method for `$currentBalance`, `$floatCurrentBalance` and `$floatAmount` as an example? – Professor Abronsius Jan 13 '16 at 14:31
  • Currency should never be stored/calculated as float values. Use integers in cents (or whatever precision you require). Floats are inherently imprecise. – Halcyon Jan 13 '16 at 14:35
  • @Halcyon I don't need to store the data in different types. All I need is some help on how to compare float values. – Michele La Ferla Jan 13 '16 at 14:36
  • 2
    You say that the return value from `getBalance` is an object ( array? ) - yet you use `$floatCurrentBalance=floatval($currentBalance)` ~ surely if it is an object/array then you would need to access the value contained within ? – Professor Abronsius Jan 13 '16 at 14:36
  • 3
    As above, `$currentBalance` is an array. You need to access the specific array key, something like `$floatCurrentBalance=floatval($currentBalance['balance'])` Or better yet have `getBalance` actually return a float and not just the database row as an array – Steve Jan 13 '16 at 14:38
  • @RamRaider no its a single value since I am getting the balance for a single user. I called it as an object as I am returning it in the function, and then calling that same method in the storeNewTicket function. `$floatAmount` and `$floatCurrentBalance` are created in the stroreNewTicket function. `$floatAmount` takes the value of the amount sent as a parameter in the query string, while `$floatCurrentBalance` takes the value of the return value from the getBalance function. – Michele La Ferla Jan 13 '16 at 14:41
  • I can have the query in getBalance() function return a float value. It is saved as a decimal in the database. – Michele La Ferla Jan 13 '16 at 14:42
  • @Steve getBalance does not return an array, as it only returns the balance of a unique user. Hence it is a single value. I am positive about this. – Michele La Ferla Jan 13 '16 at 14:44
  • 2
    `$balance = $stmt->get_result()->fetch_assoc()` ~ that will return an array not a single value. From the manual `"mysqli_result::fetch_assoc -- mysqli_fetch_assoc — Fetch a result row as an associative array"` – Professor Abronsius Jan 13 '16 at 14:44
  • @codedByMi please see: http://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency - you're right that if you use integers your current problem doesn't go away (you're probably not compring what you think you're comparing). But I would strongly encourage you not to use float for currency. – Halcyon Jan 13 '16 at 14:46
  • 2
    unless `fetch_assoc()` is your own method, on a userland class, and not the php built in method, then `$currentBalance` certainly is an array, probably with a single element. Why not `var_dump($this->getBalance($userId))` and check for yourself – Steve Jan 13 '16 at 14:46
  • @Steve @RamRaider no it is an sqli function. You are most probably right to state that `getBalance()` returns an array with a single element in it. So how would you suggest to call it and convert it to a float? @Halcyon thanks, I will read and evaluate. – Michele La Ferla Jan 13 '16 at 14:49
  • In your `getBalance` function use `return $balance['balance'];`? – Professor Abronsius Jan 13 '16 at 14:52
  • 1
    `$currentBalance['balance']` will access the float. I suggest you change it in the `getBalance()` function thoughj: `return $balance['balance'];` For good measure, you can rename the variable used in that function: `$row = $stmt->get_result()->fetch_assoc(); $stmt->close(); return $row['balance'];` The code will function the same, but it wont be as confusing for future you when you come back to make changes – Steve Jan 13 '16 at 14:52
  • thankyou both, I will try. – Michele La Ferla Jan 13 '16 at 14:52
  • still same error, I have updated the code. – Michele La Ferla Jan 13 '16 at 14:59
  • 1
    OK, well you just need to do some basic debugging steps. `var_dump()` the variables you are using, such as `$currentBalance`, `$floatCurrentBalance` and `$floatAmount` then you will see what each one holds and why its not working – Steve Jan 14 '16 at 12:16
  • ok thanks I found where the problem actually was. My `getBalance()` method was actually returning the value 1 when being converted to a float. 1 was the position of the record in the array. changing the declaration of `$floatCurrentBalance` to: `$floatCurrentBalance = floatval($currentBalance['balance']);` Thank you all again. Wouldn't have solved this without your feedback. – Michele La Ferla Jan 14 '16 at 14:14

2 Answers2

2

Please use the BC Math functions when working with floats. For comparing floats use bccomp.

Returns 0 if the two operands are equal, 1 if the left_operand is larger than the right_operand, -1 otherwise.

Beware that the third parameter is the number of digits after the decimal place.

moorscode
  • 801
  • 6
  • 13
0

I found where the problem actually was. My getBalance() method was actually returning the value 1 when being converted to a float. 1 was the position of the record in the array. Changing the declaration of $floatCurrentBalance to: $floatCurrentBalance = floatval($currentBalance['balance']);

Michele La Ferla
  • 6,775
  • 11
  • 53
  • 79