---
title: "Convert a string to integer with PHP"
url: https://www.exakat.io/convert-a-string-to-integer/
date: 2026-01-12
modified: 2026-01-13
author: "dams"
description: "Convert a string to integer with PHP PHP 8.5 provides a new error message when one tries to convert a string to integer with PHP. The float-string “%s” is not..."
categories:
  - "Code auditing"
tags:
  - "integer"
  - "php"
image: https://www.exakat.io/wp-content/uploads/2026/01/galette.320.jpg
word_count: 1807
---

# Convert a string to integer with PHP

# Convert a string to integer with PHP

PHP 8.5 provides a new error message when one tries to convert a string to integer with PHP.

[`The float-string “%s” is not representable as an int, cast occurred`](https://php-errors.readthedocs.io/en/latest/messages/the-float-string--%22%25s-%22-is-not-representable-as-an-int%2C-cast-occurred.html)

This is new with this version, and besides the warning itself, it is not even a [changed behavior](https://php-changed-behaviors.readthedocs.io/en/latest/). It is the classic PHP behavior when casting a string into an integer. Let's see what is happening here.

## Convert a string to integer

The most common way to convert a string to integer is to use the `(int)` cast operator. It takes anything, and then, returns an integer. This is quite safe, and also an impressive feat as the incoming type is really `mixed`.

## Convert a string to integer, with a warning

Obviously, there are several situations where the conversion to integer fails. For example, when the string does not contains numbers, it is converted to `0`.

Yet, there are no warning produced when the string is unparsable. PHP fails silently, and returns 0. It is actually a good practice to check for `0` after the cast: depending on the situation, it might actually be an error, just like `strpos()` returning false.

So, where does the warning come from? It happens when PHP manages to convert the string, but the resulting integer is larger that the largest PHP integer.

## Making sense of the conversion result

It is easy to recognize `9223372036854775807`as the value of `PHP_INT_MAX`. If you thought it was `4294967295`, then, you are still on a PHP 32-bits architecture.

When the original string yields a larger than `PHP_INT_MAX` value, PHP caps its value to the maximum, and emits a warning. This helps distinguish between an error where the string is not an integer, with a case where it is a possible integer, just a bit too big.

## And it gets weirder

And then, it gets weirder.

With 30 `1`, the string yields a `PHP_INT_MAX`and with 500 `1`, it yields a `0`.

Now... there could be a limit around `170141183460469231731687303715884105727`, which would be `PHP_INT_MAX` for a 128-bits architecture (Thanks to [bcmath](https://www.php.net/manual/en/function.bcpow.php) for the quick calculation). But a quick check also get `0` with 310 `1` in a string.

The limit is actually around another, lesser known constant, which is also a close cousin of `PHP_INT_MAX` : `PHP_FLOAT_MAX`. It is `1.7976931348623E+308`.

## And then, some edge cases

Now, no one will send a 310 character long number via HTTP to PHP, for conversion. This looks suspicious enough to be the work of some intrusion attempt, or a script kiddy, or simply, a bug.

Yet, while looking at the maximum float, one may recognize something we have skipped so far: an integer string is not build only with digits. We can see `.`, `E` and `+` in the number. All those look like special characters.... let's check them.

### Space

Let's start with space, ``, which is not listed above but comes immediately to mind. Spaces are automatically trimmed from the beginning and the end of the string. Spaces, and also new line, carriage return, both tabulations, and line feed.

## Non space, non digit chars

When the space is in the middle of the string, PHP stops the conversion, and returns the integer so far. It is actually the same behavior when the string is partially made of digits. PHP parse what it can, and then, stops at the first weird character.

### And here comes the E

One letter that is not weird in a number is `E`. It is used to build the decimal format, as we saw with `PHP_FLOAT_MAX`. And it gets a special behavior:

`E` is part of the decimal format, and represents the separator between the mantis and the exponent. So, PHP reads it as `123 * 10 ^ 4` and ends up with `1230000`. So, the string is much larger.

At that point, it is interesting to note that there is no more need for a long string to break the size of integers.

### The case of the dot

Now that `E` has been introduced, the last weird character is dot `.`. It is also a part of the decimal format, and, when used alone in the string, its trailing characters are abandonned: after all, they are part of the decimal part of the number.

When the `.` has a following `E`, then the exponent is applied. In the example above, it moves the comma two positions to the right, and only the final `6` is abandonned. Note that this is not a rounding, but a truncature: the `6` is not even processed.

### Plus and Minus

Finally, plus `+` and minus `-` are accepted in the string. They must be at the beginning of the string, and alone (unlike PHP which parses multiple occurrences of them). A second sign may be used with the exponent too.

## The use of the (int) warning

The warning that PHP 8.5 emits with the cast to integer does not change anything to the way PHP parses numbers. This process has been for decades, and it is not ready to change.

Now, the emission of the warning leads to more work. Hopefully, it is not displayed directly to the user on the web application. A quick search on your favorite search engine yields quite a few online apps that are displaying it (not naming any culprits, find your own).

A better approach is to use the [display_errors](https://www.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)directive, and set it to `0` (or a very large cast string...) and rather, use [log_errors](https://www.php.net/manual/en/errorfunc.configuration.php#ini.log-errors).

Yet, this means that the devops have a new error message polluting their logs, and it needs to be addressed in the code.

The question becomes :

## How to check when a string can be converted to integer?

Indeed, it would be nice to have an equivalent of `json_validate()`: it validates the string, but does not parse the string. That would skip the warning, and allow the code to handle the weird situation immediatly.

But how to do that? Here are several solutions.

## Use intval()

[`intval`](https://www.php.net/manual/en/function.intval.php) yields the same warning when the string is too big for an integer.

## Use settype()

[`settype`](https://www.php.net/manual/en/function.settype.php) yields the same warning when the string is too big for an integer. Also, nobody uses that function.

## Use is_int()

[`is_int`](https://www.php.net/manual/en/function.is-int.php) checks the type of the variable. It is already known that is a `string`, so this fails. Yet, everyone tries it, at least once.

## Use is_numeric()

[`is_numeric`](https://www.php.net/manual/en/function.is-numeric.php) checks if the string may be converted to a number. That means both integers and decimals. So, if the string is a valid decimal, but not a valid integer, the warning still happens at cast time.

Also, is_numeric() does not take into account the limits integers not decimals, so it reports that 3000 ones is a valid number. And it is not.

## Big number functions: BCMath and GMP

PHP has, at least, two extensions to handle really large numbers: [`bccomp`](https://www.php.net/manual/en/function.bccomp.php) and [`gmp_cmp`](https://www.php.net/manual/en/function.gmp-cmp.php). They both take in strings, or integers, so this works as an early warning system.

In both cases, they do not support numeric-strings like PHP, in particular `E` or any non-digit character. These require another try/catch structure to be safe.

## The filter extension

Closer to our use case is the filter extension. This extensions has a few functions to validate incoming data: in this case, [`filter_var`](https://www.php.net/manual/en/function.filter-var.php). There is a dedicated option `FILTER_VALIDATE_INT` for that purpose, with a side option:

The `max_range` option works with its default values, but also, with other values, as long as it is in the valid range of PHP integers (indeed, it is possible to specify `max_range` as ... a string).

## The revenge of the noscream

Finally, there is a valid option: `@`. It doesn't change anything to the string interpretation, provides backward compatibility, and ... hides warnings!

`@` is usually slow, but it might be faster than calling a separate function to avoid it. It is also easier to complete the current syntax.

To be honest, I never though about using `@` on a cast operator (it works!), nor about recommending using it in 2026. But, there we are.

# Converting a string to integer is not obvious

As usual, there is a lot of knowledge to gain by looking at how the code works.

The most interesting part here is how it might be easy to trigger warnings and strange behaviors on application, by feeding them with too large integers. Such integers might be validated, and used in the database as primary key.

The damage might not be important. But it will create strange errors in the logs, which might be difficult to interpret and fix. Hopefully, this post might help understanding the situation, and taking the right steps to mitigate it.

Happy Code Auditing!