Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

eriktobben's avatar

Problem with value as integer - shows different values

Hi!

I am having an issue storing order data in the database. I convert all amounts to cents to be stored as integer in the database. The field net_amount has the value of 246320 and tax_amount has 61580, both set as integers.

When combining these like this: $order->net_amount + $order->tax_amount I get the result: 307900.0

But to remove the decimal point, I cast it to integers: (int) $order->net_amount + (int) $order->tax_amount I get the result: 307898

Why is the latter missing two cents?

0 likes
34 replies
LaryAI's avatar
Level 58

The issue you're facing is due to the order of operations in your code. When you cast the values to integers separately, you're performing the addition after the casting. To fix this, you need to group the addition operation before casting the result to an integer.

Here's the corrected code:

(int) ($order->net_amount + $order->tax_amount)

By wrapping the addition operation in parentheses, you ensure that the addition is performed first, and then the result is cast to an integer. This will give you the correct result of 307900.

1 like
eriktobben's avatar

@LaryAI I tested doing it like this (int)($order->net_amount + $order->tax_amount), but I still get 307899.

krisi_gjika's avatar

"... both set as integers. When combining these like this: $order->net_amount + $order->tax_amount I get the result: 307900.0" - if they are both integers their sum can't be float. At least one of your values is a float.

eriktobben's avatar

@krisi_gjika You are right in a sense, when I do gettype() for both variables, it returns double. But it is stored as integer in the database. Where is that conversion happening?

eriktobben's avatar

I now tried casting them to integer in the model, and that changed the type, but I still get the value 307898 after doing $order->net_amount + $order->tax_amount.

krisi_gjika's avatar

@eriktobben either your model casts, some model attribute/accesor or somewhere in your business logic. Please provide more code of what you are doing, how you are storing/retrieving the data.

eriktobben's avatar

@krisi_gjika Here is part of the array that is being sent to the payment gateway:

$order = Order::where('order_number', $orderNumber)->firstOrFail();

[
'merchant_reference1' => $order->order_number,
'merchant_reference2' => (string) $order->public_id,
'order_amount' => (int) ($order->net_amount + $order->tax_amount),
'order_tax_amount' => (int) $order->tax_amount,
]

Model casts:

protected $casts = [
        'payment_authorized_at' => 'datetime',
        'net_amount' => 'integer',
        'tax_amount' => 'integer',
    ];

eriktobben's avatar

When only doing (int) $order->net_amount the value is 246319 which is 246320 in the database. So it seems like the issue is happening with the value of net_amount .

Snapey's avatar

@eriktobben double check the column type in the database. Inspect the actual database not just the migration

you could also check with DB and query builder, bypassing the model

eriktobben's avatar

@martinbean Sure :)

"customer_order_reference" => null
"comments" => null
"net_amount" => 246320.0
"tax_amount" => 61580.0
"ip_address" => "127.0.0.1"
"utm_data" => null
eriktobben's avatar

@martinbean Yes, I see that, but I can't understand how that is happening. I even try to dump gettype($order->net_amount) and the value is ^ "integer"

eriktobben's avatar

@martinbean I tried adding a method to the model to return the values, but same issue there.

public function orderAmounts()
    {
        return [
            'net_amount' => $this->net_amount,
            'tax_amount' => $this->tax_amount,
            'total' => $this->net_amount + $this->tax_amount,
        ];
    }

returns

[
  "net_amount" => 246319
  "tax_amount" => 61579
  "total" => 307898
]
DhPandya's avatar

@eriktobben So what is the issue? 246319+61579=307898. I didn't find any mistake here. BTW have you casted your properties inside the model ?

eriktobben's avatar

@DhPandya Hi! That is correct, but the value in the database is 246320 + 61580 = 307900. I have checked that the database field is integer, and that net_amount and tax_amount is cast to integer in the model.

The issue is that there is a 2 cent different shown in PHP compared to the database. 307898 (php) - 307900 (db) = -2

DhPandya's avatar

@eriktobben Have you tried using number_format(246320,2); ? If you want to store decimal values in your database then you should set the type of your column to decimal. Like decimal(8,2)

eriktobben's avatar

@DhPandya I do not want to store decimal values, that is why I convert the value to cents with $amount * 100 before saving to database.

Snapey's avatar

what values do you actually have in your database? Maybe you are confused as to what the result should actually be?

Check with a DB tool like phpMyAdmin or Sequel Ace

eriktobben's avatar

@Snapey Including tax the value should be NOK 3079 (after /100). Using Table Plus the values are 246320 (net_amount) and 61580 (tax_amount) = 307900 / 100 = 3079.

Both database fields are integer, and gettype() returns 'Integer' on both fields, but in PHP the value is still 307898. If I remove the cast to integer it shows 307900.0

It looks like each field is showing 1 less making the total 2 less than expected when casting to integer in PHP.

^ array:3 [▼
  "net_amount" => 246319 (is 246320 in db)
  "tax_amount" => 61579 (is 61580 in db)
  "total" => 307898
]
eriktobben's avatar

If I change the casts to string it seems to works:

^ array:3 [▼
  "net_amount" => "246320"
  "tax_amount" => "61580"
  "total" => 307900
]

But I still don't understand why this is happening...

eriktobben's avatar

Using Artisan Tinker, it works, even without casting to integer in the model:

[
     "net_amount" => 246320,
     "tax_amount" => 61580,
     "total" => 307900,
 ]
tangtang's avatar

@eriktobben The reason you are missing two cents when you cast the values to integers is due to the way PHP handles floating-point numbers and type casting.

In PHP, when you cast a floating-point number to an integer using (int), it truncates the decimal portion without rounding. So, in your case, when you cast $order->net_amount and $order->tax_amount to integers separately and then add them, you are effectively truncating the cents part of each value separately. This can lead to a loss of precision in the final result.

have you try

(int) round($order->net_amount) + (int) round($order->tax_amount)

test it with other number, and make sure the result is like what you want.

eriktobben's avatar

@Snapey Of course :)

class Order extends Model
{
    use HasFactory, SoftDeletes;

    protected $casts = [
        'payment_authorized_at' => 'datetime',
        'net_amount' => 'integer',
        'tax_amount' => 'integer',
    ];

    public function items(): HasMany
    {
        return $this->hasMany(OrderItem::class, 'order_id');
    }

    public function company(): BelongsTo
    {
        return $this->belongsTo(Company::class, 'company_id');
    }

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    public function files(): HasMany
    {
        return $this->hasMany(OrderFile::class, 'order_id');
    }

    public function shipments(): HasMany
    {
        return $this->hasMany(OrderShipment::class, 'order_id');
    }

    public function transactions(): HasMany
    {
        return $this->hasMany(OrderTransaction::class, 'order_id');
    }

    public function paymentMethod()
    {
        return (new PaymentService)->getMethod($this->payment_method_id);
    }

    public function orderAmounts()
    {
        return [
            'net_amount' => $this->net_amount,
            'tax_amount' => $this->tax_amount,
            'total' => $this->net_amount + $this->tax_amount,
        ];
    }
}
Tray2's avatar

@eriktobben Do you have a github repository that we can look at?

Somewhere in your code you are storing the values as floats or decimals, otherwise you wouldn't get that type of error.

Snapey's avatar

@eriktobben I replicated everything you have and got the expected result.

How are you displaying the results of your tests?

eriktobben's avatar

@Snapey That is weird. I have just dd'ed $order->net_amount, $order->tax_amount or $order->orderAmounts()

So I would assume that $order->net_amount straight from the Eloquent query should not modify the data type from the database unless it is set in the $casts array, right? Or are there other places which can manipulate the data?

I also assume that no matter what the data type is when storing the data to the database, the data would be converted to the fields data type? So if the net_amount value was a float at save, as long as the field type is integer in the database and the value is correct in the database it would not carry over when retrieving the data?

eriktobben's avatar

I think I found the issue. I thought that the Order resource was retrieved from the database, when in fact the resource was returned from the store logic, which (I didn't know this) seems to only return the values added when creating the resource, not data from the resource itself. So when it stored the original values from PHP (which is float) to the database (which is integer) it returns the model with the fields set as float.

This also means that the values in the database is correct as the type is set to integer.

When I fetched the model again from the database it returns the correct types and thus the correct values.

I want to thank all of you for helping me with this issue, and I'm sorry if this is common knowledge, but this was news to me.

Snapey's avatar

@eriktobben sounds like you need a couple of mutators to convert the saved values to ints rather than letting the database do it.

to be honest I'm surprised the casting does not do this.

eriktobben's avatar

@Snapey Yes, I have made sure that the value before saving to db is converted correctly.

I agree, I thought that it did.

Thanks again!

Please or to participate in this conversation.