41

Do you know of a function that can check if a string contains an integer?

Here's how I'd expect it to work:

holds_int("23") // should return true.  
holds_int("2.3") // should return false.  
holds_int("qwe") // should return false.
Emanuil Rusev
  • 34,563
  • 55
  • 137
  • 201

15 Answers15

74
if((string)(int)$var == $var) {
    echo 'var is an integer or a string representation of an integer';
}

Example results:

var_dump( test(1)             ); // TRUE
var_dump( test('1')           ); // TRUE
var_dump( test('1.0')         ); // TRUE
var_dump( test('1.1')         ); // false
var_dump( test('0xFF')        ); // false
var_dump( test('0123')        ); // TRUE
var_dump( test('01090')       ); // TRUE
var_dump( test('-1000000')    ); // TRUE
var_dump( test('+1000000')    ); // TRUE
var_dump( test('2147483648')  ); // false
var_dump( test('-2147483649') ); // false

See Gordon's answer below for how this would behave differently if === were used for comparison instead of ==.

Jhong
  • 2,714
  • 22
  • 19
  • 3
    this should test with `===` and make sure the number is inside the integer range – Gordon Jul 31 '10 at 09:50
  • 6
    === won't work if $var actually is an integer. == will, regardless of whether it is a string or an int. OP didn't ask for that specifically, but it seems a bit perverse to return false if it actually is an integer. – Jhong Jul 31 '10 at 09:55
  • There's also no point in the additional check for the PHP_INT_MAX -- the above will return false if the integer is out of range anyway. Why add the additional check? – Jhong Jul 31 '10 at 09:57
  • I dont think so: the OP asked for if *string* holds *integer*. If you pass in an integer, it's not a string, so ... – Gordon Jul 31 '10 at 09:58
  • 1
    @Gordon: Casting to integer will always yield a valid integer. – Gumbo Jul 31 '10 at 09:59
  • @Gumbo Ok, I stand corrected. You dont need the bitrange check then. And let's leave it up to the OP to decide if he needs `===` or `==` comparison. There is edge cases, e.g. '1.0', hex and octals. – Gordon Jul 31 '10 at 10:24
  • 13
    I'd rather do something like `(string)(int)$var === (string)$var`, to eliminate what I see as a false positive in your list, `1.0`. – nyson Jun 28 '12 at 07:35
  • 1
    @nyson, you should make that an answer so I could vote for it. – Prof. Falken Apr 04 '13 at 09:28
  • `var_dump( test('2147483648') ); // false var_dump( test('-2147483649') ); // false` both return true, not false. – Shaun Dychko Feb 06 '17 at 15:29
  • Except 0123 is an int – FrancescoMM Sep 05 '18 at 15:22
14

Not the fastest method, but filter_var() is quite accurate:

function test($s)
{
    return filter_var($s, FILTER_VALIDATE_INT) !== false;
}

Here are the results based on Jhong's answer, differences marked with !!:

var_dump(test(1)            ); // true
var_dump(test('1')          ); // true
var_dump(test('1.0')        ); // false !!
var_dump(test('1.1')        ); // false
var_dump(test('0xFF')       ); // false
var_dump(test('0123')       ); // false !!
var_dump(test('01090')      ); // false !!
var_dump(test('-1000000')   ); // true
var_dump(test('+1000000')   ); // true
var_dump(test('2147483648') ); // true !! on 64bit
var_dump(test('-2147483649')); // true !! on 64bit

To allow octal integers:

function test($s)
{
   return filter_var($s, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_OCTAL) !== false;
}

Results:

var_dump(test('0123') ); // true
var_dump(test('01090')); // false !!

To allow hexadecimal notation:

function test($s)
{
   return filter_var($s, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX) !== false;
}

Results:

var_dump(test('0xFF')); // true !!
Community
  • 1
  • 1
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • 1
    I just used your function and it has problems with large numbers. Given the fact that the requirement is to check if a string contains an integer, but doesn't say how long can it be, I believe that a regular expression approach might be better in this case. For a number like 999999999999999999 it will work, but if you try for instance with a string containing the number 9999999999999999999, which is a valid integer, it will fail. – jpruiz114 Nov 26 '17 at 18:42
  • @JeanPaulRuiz sure, that's one way of interpretation, my method checks whether it can be assigned to a variable :) – Ja͢ck Nov 27 '17 at 23:33
11

Dont want to accidently turn Jhong's answer into a CW, so for the record here is the results when testing with === instead of ==.

function test($var) {
    return ((string)(int)$var === $var);
}

var_dump( test(1)             ); // returns false vs TRUE
var_dump( test('1')           ); // returns TRUE
var_dump( test('1.0')         ); // returns false vs TRUE
var_dump( test('1.1')         ); // returns false 
var_dump( test('0xFF')        ); // returns false
var_dump( test('0123')        ); // returns false vs TRUE
var_dump( test('-0123')       ); // returns false vs TRUE
var_dump( test('-1000000')    ); // returns TRUE
var_dump( test('+1000000')    ); // returns false vs TRUE
var_dump( test('2147483648')  ); // returns false
var_dump( test('-2147483649') ); // returns false
Gordon
  • 312,688
  • 75
  • 539
  • 559
  • 1
    1.0 (float) and 0123 (invalid) are better results here than my version -- I hadn't considered them! – Jhong Jul 31 '10 at 16:01
  • @Jhong using `==` will also return true for hex `0xFF` and scientific notation `-1.3e3` (e.g. both when not used as string, false if used as string) – Gordon Jul 31 '10 at 16:16
9

Update Since PHP 7.1 there are problems with using is_int() with non-numeric values, as discussed in this SO Answer. In any case, this is a very old answer and I'd really view it as something of a hack at this point so YMMV ;)

Sorry if this question has been answered but this has worked for me in the past:

First check if the string is_numeric. if it is add a 0 to the value to get PHP to covert the string to its relevant type. Then you can check if it's an int with is_int. Quick and dirty but it works for me...

$values = array(1, '2', '2.5', 'foo', '0xFF', 0xCC, 0644, '0777');

foreach ($values as $value) {
  $result = is_numeric($value) && is_int(($value + 0)) ? 'true' : 'false';
  echo $value . ': ' . $result . '<br />';
}

Results:

1: true
2: true
2.5: false
foo: false
0xFF: true
204: true
420: true
0777: true

The only problem is that it will evaluate octal values wrapped in a string literally, i.e: '0123' will simply become 123. But that's easy to address :)

Community
  • 1
  • 1
Darragh Enright
  • 13,676
  • 7
  • 41
  • 48
  • 1
    When a value is not actually a number, such as `foo`, I get the following *PHP error*: `A non-numeric value encountered`. I am using `PHP 7.1.3`. [An answer related to this](http://stackoverflow.com/a/42044413/1883256). And [They advice not to use is_int() here](https://odd.blog/2009/03/31/php-is_numeric-vs-is_int/) – Pathros May 14 '17 at 16:29
  • Thanks for your comment @Pathros - as you can see this is a 7 year old answer, so it looks like there is a change in behaviour since PHP 7.1. I'll edit my answer to make note of the change. – Darragh Enright May 14 '17 at 16:43
6

ctype_digit will do the trick:

ctype_digit($str)

  1. $str has to be a string
  2. extra spaces are not allowed
  3. no decimal points .
Yerke
  • 2,071
  • 2
  • 25
  • 23
4

If the string contains spaces, then @Jack's answer will not provide accurate result. e.g.

$var = '19   ';
if((string)(int)$var == $var) {
echo 'var is an integer or a string representation of an integer';
}

The above string will not be an int according to the above check.

So instead of using this, try following:

if(ctype_digit(trim('19  '))){
    echo 'it is digit ';
}else{
    echo 'it is not digit ';
}
Raza Ahmed
  • 2,661
  • 2
  • 35
  • 46
4

Other option

function holds_int($str)
   {
   return preg_match("/^-?[0-9]+$/", $str);
   }
nico
  • 50,859
  • 17
  • 87
  • 112
  • This (in its current form) also doesn't account for negative integers. – VolkerK Jul 31 '10 at 09:42
  • regex is a fairly resource-intensive solution to an ostensibly simple problem (I didn't downvote you mind). – Jhong Jul 31 '10 at 09:47
  • 1
    Now your regex allows `12-34`. You should use `/^-?[0-9]+$/`. If you want to reject leading zeros (which you should) use `/^-?[1-9][0-9]*$/`. – NikiC Jul 31 '10 at 09:51
  • good point about the minus in the middle, updated the code! NB: I wasn't complaining because of the downvote per se, just asking why it was not correct. As for regexp being resource intensive it really depends how often this gets called, it may not be good in certain situation but it may be absolutely ok for others. – nico Jul 31 '10 at 11:06
  • @nikic: I wouldn't reject leading zeros, "05" is a valid integer containing string IMHO. – nico Jul 31 '10 at 11:07
  • 3
    Regular Expressions: Now You Have Two Problems – webjunkie Jul 31 '10 at 11:48
2

I've been using this since long time. While all the other answers have drawbacks or special cases, if you want to detect any possible int valued thing, including 1.0 "1.0" 1e3 "007" then you better let is_numeric do its job to detect any possible PHP object that represents a number, and only then check if that number is really an int, converting it to int and back to float, and testing if it changed value.:

function isIntValued($var) {
    if(is_numeric($var)) { // At least it's number, can be converted to float
        $var=(float)$var; // Now it is a float
        return ((float)(int)$var)===$var;
    }
    return FALSE;
}

or in short

function isIntValued($var) {
    return (!is_numeric($var)?FALSE:((float)(int)(float)$var)===(float)$var);
}

Or

 function isIntValued($var) {
    return (is_numeric($var) && ((float)(int)(float)$var)===(float)$var);
}

Note that while PHP's is_int() checks if the type of variable is an integer, on the contrary the other standard PHP function is_numeric() determines very accurately if the contents of the variable (i.e. string chars) can represent a number.

If, instead, you want "1.0" and "2.00" not to be considered integers but floats (even if they have an integer value), then the other answer ( @Darragh Enright ) using is_numeric, adding zero and testing for int is probably the most correct solution:

    is_numeric($s) && is_int($s+0)
FrancescoMM
  • 2,845
  • 1
  • 18
  • 29
1

Maybe this will also help in given situation there is a function in php that already does this, its called "is_numeric()" it will return true or false accordenly..

   if(is_numeric($somestring) == True){
        echo "this string contains a integar";
    }

link: http://www.php.net/is_numeric

you said "holdsint("2") should return true, well is_numeric("2") returns True, and is_numeric("a") False, as expected, this function exists in php, no need to rewrite.

scott
  • 1,531
  • 2
  • 16
  • 29
  • 2
    This is incorrect; `is_numeric()` returns `true` for floats. – Tristan Aug 27 '14 at 18:15
  • ahh yes but like most things here, at the time of post it was correct for original question didnt mention floats, then the original poster went and edited his question so now i look like the idiot. Typical. – scott Nov 02 '16 at 00:31
0

I liked nyson's suggestion, but noticed that it will be false for '0123'. I'm now doing this:

(string)(int)$var === ltrim((string)$var, '0')

(This would have been posted as a comment @nyson, but I don't have enough privileges to do that yet).

Edited to add: If you want zero to be true, you need to do something like

(int)$var === 0 || (string)(int)$var === ltrim((string)$var, '0')
HalfTitle
  • 137
  • 1
  • 4
0

There may be two cases-

  1. You need to check for exact string format of a number(most of ans is about this one)

  2. You want to check, whether a string contains a specific number or not

    preg_match('/'.$matching_number.'/',$container_string);

Jim
  • 22,354
  • 6
  • 52
  • 80
Sadat
  • 3,493
  • 2
  • 30
  • 45
0

comparison.php:

<?php
function is_numeric_int($s)
{
  return (strval(intval($s)) === $s);
}

function print_ini($s)
{
  echo "$s: " . ( is_numeric_int($s) ? 'true' : 'false' ) . "\n";
}

print_ini('qwe');
print_ini('23');
print_ini('-23');
print_ini('23.0');
print_ini('-23.0');
?>

Test run:

$ php comparison.php 
qwe: false
23: true
-23: true
23.0: false
-23.0: false
clacke
  • 7,688
  • 6
  • 46
  • 48
0

If you use Assert library in you project (https://github.com/beberlei/assert) you can easily do it in one line:

Assertion::integerish($var);

Note: it throws an exception in case of violation the assertion.

0

Seeing that you are searching for a value in a string, I'd go for:

(bool) preg_match('/^\d+$/', '23'); // true
(bool) preg_match('/^\d+$/', '2.3'); // false
(bool) preg_match('/^\d+$/', 'qwe'); // false
xndrw
  • 78
  • 8
-3

is_int is the only what it's meant to do this work.

Rostyslav Dzinko
  • 39,424
  • 5
  • 49
  • 62
jack
  • 1,415
  • 4
  • 15
  • 22