Überprüfen, ob eine Variable in PHP eine Ganzzahl ist

78

Ich habe den folgenden Code

    $page = $_GET['p'];

    if($page == "")
    {
        $page = 1;
    }
    if(is_int($page) == false)
    {
        setcookie("error", "Invalid page.", time()+3600);
        header("location:somethingwentwrong.php");
        die();
    }
    //else continue with code

die ich zum Betrachten verschiedener "Seiten" einer Datenbank verwenden werde (Ergebnisse 1-10, 11-20 usw.). Ich kann jedoch nicht scheinen, dass die Funktion is_int () richtig funktioniert. Wenn ich "1" in die URL (noobs.php? P = 1) setze, erhalte ich den ungültigen Seitenfehler sowie etwas wie "asdf".

Ahota
quelle

Antworten:

181

Es is_numeric()ist eine schlechte Idee, zu überprüfen, ob eine Variable eine Ganzzahl ist. Diese Funktion wird wieder TRUEfür 3.14zum Beispiel. Es ist nicht das erwartete Verhalten.

Um dies richtig zu machen, können Sie eine der folgenden Optionen verwenden:

Betrachtet man dieses Variablenarray:

$variables = [
    "TEST 0" => 0,
    "TEST 1" => 42,
    "TEST 2" => 4.2,
    "TEST 3" => .42,
    "TEST 4" => 42.,
    "TEST 5" => "42",
    "TEST 6" => "a42",
    "TEST 7" => "42a",
    "TEST 8" => 0x24,
    "TEST 9" => 1337e0
];

Die erste Option (FILTER_VALIDATE_INT Weg):

# Check if your variable is an integer
if ( filter_var($variable, FILTER_VALIDATE_INT) === false ) {
  echo "Your variable is not an integer";
}

Ausgabe :

TEST 0 : 0 (type:integer) is an integer ✔
TEST 1 : 42 (type:integer) is an integer ✔
TEST 2 : 4.2 (type:double) is not an integer ✘
TEST 3 : 0.42 (type:double) is not an integer ✘
TEST 4 : 42 (type:double) is an integer ✔
TEST 5 : 42 (type:string) is an integer ✔
TEST 6 : a42 (type:string) is not an integer ✘
TEST 7 : 42a (type:string) is not an integer ✘
TEST 8 : 36 (type:integer) is an integer ✔
TEST 9 : 1337 (type:double) is an integer

Die zweite Option (CASTING COMPARISON-Methode):

# Check if your variable is an integer
if ( strval($variable) !== strval(intval($variable)) ) {
  echo "Your variable is not an integer";
}

Ausgabe :

TEST 0 : 0 (type:integer) is an integer ✔
TEST 1 : 42 (type:integer) is an integer ✔
TEST 2 : 4.2 (type:double) is not an integer ✘
TEST 3 : 0.42 (type:double) is not an integer ✘
TEST 4 : 42 (type:double) is an integer ✔
TEST 5 : 42 (type:string) is an integer ✔
TEST 6 : a42 (type:string) is not an integer ✘
TEST 7 : 42a (type:string) is not an integer ✘
TEST 8 : 36 (type:integer) is an integer ✔
TEST 9 : 1337 (type:double) is an integer

Die dritte Option (CTYPE_DIGIT-Methode):

# Check if your variable is an integer
if ( ! ctype_digit(strval($variable)) ) {
  echo "Your variable is not an integer";
}

Ausgabe :

TEST 0 : 0 (type:integer) is an integer ✔
TEST 1 : 42 (type:integer) is an integer ✔
TEST 2 : 4.2 (type:double) is not an integer ✘
TEST 3 : 0.42 (type:double) is not an integer ✘
TEST 4 : 42 (type:double) is an integer ✔
TEST 5 : 42 (type:string) is an integer ✔
TEST 6 : a42 (type:string) is not an integer ✘
TEST 7 : 42a (type:string) is not an integer ✘
TEST 8 : 36 (type:integer) is an integer ✔
TEST 9 : 1337 (type:double) is an integer

Die vierte Option (REGEX-Methode):

# Check if your variable is an integer
if ( ! preg_match('/^\d+$/', $variable) ) {
  echo "Your variable is not an integer";
}

Ausgabe :

TEST 0 : 0 (type:integer) is an integer ✔
TEST 1 : 42 (type:integer) is an integer ✔
TEST 2 : 4.2 (type:double) is not an integer ✘
TEST 3 : 0.42 (type:double) is not an integer ✘
TEST 4 : 42 (type:double) is an integer ✔
TEST 5 : 42 (type:string) is an integer ✔
TEST 6 : a42 (type:string) is not an integer ✘
TEST 7 : 42a (type:string) is not an integer ✘
TEST 8 : 36 (type:integer) is an integer ✔
TEST 9 : 1337 (type:double) is an integer
CaM2091
quelle
10
Achten Sie auf FILTER_VALIDATE_INT (Ihr bevorzugter Weg) 0 gibt false zurück!
Niksac
13
Verwenden Sie stattdessen filter_var ($ int, FILTER_VALIDATE_INT)! == false.
Niksac
1
Ich denke da ist ein! fehlt bei if(filter_var($variable, FILTER_VALIDATE_INT) !== false) echo "its not an integer, oder?
Adam
3
oder der Text sollte in "es ist ein iteger" geändert werden
Adam
3
Der 'CTYPE_DIGIT-Weg' und der 'REGEX-Weg' schlagen beide für negative ganze Zahlen fehl. Der 'REGEX-Weg' kann behoben werden, indem überprüft wird, ob ein führendes negatives Vorzeichen ( -?) vorhanden ist, aber ich glaube nicht, dass ctype_digitdies auf prägnante Weise verwendet werden kann, um nach negativen ganzen Zahlen zu suchen. Der gebuchte Code kann auch nicht die entsprechenden Ausgaben erzeugen.
Dave F
33

Alle $_GETParameter haben einen String-Datentyp, daher is_intwird immer false zurückgegeben.

Sie können dies sehen, indem Sie anrufen var_dump:

var_dump($_GET['p']); // string(2) "54"

Die Verwendung is_numericliefert das gewünschte Ergebnis (wohlgemerkt, das Werte wie :) zulässt 0x24.

Tim Cooper
quelle
3
Warnung: Dies gibt mehr als nur Ints zurück. Verwenden Sie eine der anderen unten aufgeführten Lösungen.
Nathan Bell
26

Wenn der Browser pden Querystring sendet , wird er als Zeichenfolge und nicht als Int empfangen. is_int()wird daher immer false zurückgeben.

Versuchen Sie stattdessen is_numeric()oderctype_digit()

Michael Berkowski
quelle
11

Nur zum Spaß habe ich einige der genannten Methoden getestet und eine, die ich jahrelang als Lösung verwendet habe, wenn ich weiß, dass meine Eingabe eine positive Zahl oder ein String-Äquivalent ist.

Ich habe dies mit 125.000 Iterationen getestet, wobei jede Iteration denselben Satz von Variablentypen und -werten durchlief.

Methode 1: is_int($value) || ctype_digit($value)
Methode 2: (string)(int)$value == (string)$value
Methode 3: strval(intval($value)) === strval($value)
Methode 4: ctype_digit(strval($value))
Methode 5: filter_var($value, FILTER_VALIDATE_INT) !== FALSE
Methode 6: is_int($value) || ctype_digit($value) || (is_string($value) && $value[0] === '-' && filter_var($value, FILTER_VALIDATE_INT) !== FALSE)

Methode 1: 0,0552167892456
Methode 2: 0,126773834229
Methode 3: 0,143012046814
Methode 4: 0,0979189872742
Methode 5: 0,112988948822
Methode 6: 0,0858821868896

(Ich habe nicht einmal die Regex getestet, ich meine, ernsthaft ... Regex dafür?)

Zu beachtende Punkte:
Methode 4 gibt für negative Zahlen (negative Ganzzahl oder Zeichenfolgenäquivalent) immer false zurück. Dies ist eine gute Methode, um konsistent zu erkennen, dass ein Wert eine positive Ganzzahl ist.
Methode 1 gibt true für eine negative Ganzzahl zurück, false jedoch für eine Zeichenfolge, die einer negativen Ganzzahl entspricht. Verwenden Sie diese Methode daher nur, wenn Sie sicher sind, dass Ihre Eingabe niemals eine negative Zahl in Zeichenfolgen- oder Ganzzahlform enthält Ihr Prozess wird von diesem Verhalten nicht unterbrochen.

Schlussfolgerungen
Wenn Sie also sicher sind, dass Ihre Eingabe keine negative Zahl enthält, ist es fast doppelt so schnell, eine Ganzzahl zu verwenden is_intund ctype_digitzu überprüfen. Die Verwendung von Methode 1 mit einem Fallback auf Methode 5, wenn die Variable eine Zeichenfolge und das erste Zeichen ein Bindestrich ist, ist die nächstschnellste (insbesondere, wenn ein Großteil der Eingabe tatsächliche Ganzzahlen oder positive Zahlen in einer Zeichenfolge sind). Alles in allem filter_var($value, FILTER_VALIDATE_INT) !== FALSEgewinnt es , wenn Sie eine solide Konsistenz benötigen und keine Ahnung haben, wie der Datenmix hereinkommt, und wenn Sie mit Negativen konsistent umgehen müssen, gewinnt dies.

Code zum Abrufen der obigen Ausgabe:

$u = "-10";
$v = "0";
$w = 0;
$x = "5";
$y = "5c";
$z = 1.44;

function is_int1($value){
    return (is_int($value) || ctype_digit($value));
}

function is_int2($value) {
    return ((string)(int)$value == (string)$value);
}

function is_int3($value) {
    return (strval(intval($value)) === strval($value));
}

function is_int4($value) {
    return (ctype_digit(strval($value)));
}

function is_int5($value) {
    return filter_var($value, FILTER_VALIDATE_INT) !== FALSE;
}

function is_int6($value){
    return (is_int($value) || ctype_digit($value) || (is_string($value) && $value[0] === '-' && filter_var($value, FILTER_VALIDATE_INT)) !== FALSE);
}

$start = microtime(TRUE);
for ($i=0; $i < 125000; $i++) {
  is_int1($u);
  is_int1($v);
  is_int1($w);
  is_int1($x);
  is_int1($y);
  is_int1($z);
}
$stop = microtime(TRUE);
$start2 = microtime(TRUE);
for ($j=0; $j < 125000; $j++) {
  is_int2($u);
  is_int2($v);
  is_int2($w);
  is_int2($x);
  is_int2($y);
  is_int2($z);
}
$stop2 = microtime(TRUE);
$start3 = microtime(TRUE);
for ($k=0; $k < 125000; $k++) {
  is_int3($u);
  is_int3($v);
  is_int3($w);
  is_int3($x);
  is_int3($y);
  is_int3($z);
}
$stop3 = microtime(TRUE);
$start4 = microtime(TRUE);
for ($l=0; $l < 125000; $l++) {
  is_int4($u);
  is_int4($v);
  is_int4($w);
  is_int4($x);
  is_int4($y);
  is_int4($z);
}
$stop4 = microtime(TRUE); 

$start5 = microtime(TRUE);
for ($m=0; $m < 125000; $m++) {
  is_int5($u);
  is_int5($v);
  is_int5($w);
  is_int5($x);
  is_int5($y);
  is_int5($z);
}
$stop5 = microtime(TRUE); 

$start6 = microtime(TRUE);
for ($n=0; $n < 125000; $n++) {
  is_int6($u);
  is_int6($v);
  is_int6($w);
  is_int6($x);
  is_int6($y);
  is_int6($z);
}
$stop6 = microtime(TRUE); 

$time = $stop - $start;  
$time2 = $stop2 - $start2;  
$time3 = $stop3 - $start3;  
$time4 = $stop4 - $start4;  
$time5 = $stop5 - $start5;  
$time6 = $stop6 - $start6;  
print "**Method 1:** $time <br>";
print "**Method 2:** $time2 <br>";
print "**Method 3:** $time3 <br>";
print "**Method 4:** $time4 <br>";  
print "**Method 5:** $time5 <br>";  
print "**Method 6:** $time6 <br>";  
Jonathan Falkner
quelle
8

/! \ Beste Antwort ist nicht korrekt, is_numeric () gibt true für Integer UND alle numerischen Formen wie "9.1" zurück.

Nur für Ganzzahlen können Sie das unfreundliche preg_match ('/ ^ \ d + $ /', $ var) oder den expliziten und zweimal schnelleren Vergleich verwenden:

if ((int) $var == $var) {
    // $var is an integer
}

PS: Ich weiß, dass dies ein alter Beitrag ist, aber immer noch der dritte in Google, der nach "PHP ist Ganzzahl" sucht.

job3dot5
quelle
1
Dies ist falsch, da diese Bedingung auch dann erfüllt ist, wenn z. B. $ var = "9". Es sollte if ((int) $ var === $ var) sein. $ a == $ b Gleich TRUE, wenn $ a nach dem Jonglieren gleich $ b ist. $ a === $ b Identisch WAHR, wenn $ a gleich $ b ist und sie vom gleichen Typ sind.
Valerij Vasilcenko
Beachten Sie, dass (int) $varNull zurückgegeben wird, wenn die Zeichenfolge nicht in eine Zahl umgewandelt werden kann. Also: (int) 'banana' === 0
Ignacio Segura
Als Kommentare herabgestuft, ist diese Antwort nicht richtig.
EAmez
@IgnacioSegura Ist es also sicher, wenn es nach einem Validator wie verwendet wird if (is_numeric($var) && ((int) $var == $var)) {...}?
Guney
@GuneyOzsan, was Sie vorschlagen, klingt richtig, aber um ehrlich zu sein, habe ich vor zwei Jahren aufgehört, in PHP zu programmieren, und ich habe viele Dinge vergessen. Entschuldigung, ich könnte nicht hilfsbereiter sein.
Ignacio Segura
3

Sie können versuchen, einen Casting-Operator zu verwenden, um ihn in eine Ganzzahl zu konvertieren:

$page = (int) $_GET['p'];

if($page == "")
{
    $page = 1;
}
if(empty($page) || !$page)
{
    setcookie("error", "Invalid page.", time()+3600);
    header("location:somethingwentwrong.php");
    die();
}
//else continue with code
Drewdin
quelle
1
Nun, wenn Sie es zuerst in eine ganze Zahl is_intis_numeric
umwandeln
2

Werte $_GETsind immer Zeichenfolgen - so kommen GET-Parameter. Daher is_int($_GET[...])ist immer falsch.

Mit is_numeric können Sie testen, ob eine Zeichenfolge nur aus Ziffern besteht (dh als Zahl interpretiert werden kann) .

Phihag
quelle
2

Ich hatte gerade ein ähnliches Problem!

Sie können die filter_input()Funktion mit FILTER_VALIDATE_INTund verwenden FILTER_NULL_ON_FAILURE, um nur ganzzahlige Werte aus der $_GETVariablen herauszufiltern . Funktioniert ziemlich genau! :) :)

Überprüfen Sie meine Frage hier: Wie überprüfe ich , ob eine Variable in $ _GET Array eine Ganzzahl ist?

maxxon15
quelle
2

Die Lösung von doctormad ist nicht korrekt. Versuche dies:

$var = '1a';
if ((int) $var == $var) {
    var_dump("$var is an integer, really?");
}

Dies wird gedruckt

1a ist wirklich eine ganze Zahl? "

Verwenden Sie filter_var () mit dem Argument FILTER_VALIDATE_INT

$data = Array('0', '1', '1a', '1.1', '1e', '0x24', PHP_INT_MAX+1);
array_walk($data, function ($num){
$is_int = filter_var($num, FILTER_VALIDATE_INT);
if ($is_int === false)
var_dump("$num is not int");
});

Dies wird gedruckt

1a is not int 
1.1 is not int
1e is not int
0x24 is not int
9.2233720368548E+18 is not int
Aleksandr
quelle
Ich mochte Ihre Lösung ... akzeptiert 0, lehnt jedoch nicht ganzzahlige Zeichen ab.
user2662680
1
$page = (isset($_GET['p']) ? (int)$_GET['p'] : 1);
if ($page > 0)
{
  ...
}

Versuchen Sie zunächst zu gießen und zu überprüfen, ob es sich um eine Zahl handelt.

Brad Christie
quelle
Der Anruf is_int()hierher ist überflüssig. Die Variable $pageist hier aufgrund der vorherigen Codezeile immer eine Ganzzahl.
Hammerite
@ netcoder / @ Hammerite: Touche, ich habe vergessen, dass ein Cast den Standardwert liefert. Sollte prüfen, ob >0. Entschuldigen Sie.
Brad Christie
1

Als ich anfing, es zu lesen, bemerkte ich, dass ihr vergessen habt, ob wir int, string, null oder Boolean haben. Also ich denke gettype()sollte als 1. Antwort sein. Erklären Sie: Wenn wir also haben $test = [1,w2,3.45,sasd];, fangen wir an, es zu testen

foreach ($test as $value) {
        $check = gettype($value);
        if($check == 'integer'){
            echo "This var is int\r\n";
        }
        if($check != 'integer'){
            echo "This var is {$check}\r\n";
        }
}

Und Ausgabe:

> This var is int 
> This var is string 
> This var is double 
> This var is string

Ich denke, dies ist der einfachste Weg, um zu überprüfen, ob unsere Variable int, string, double oder Boolean ist.

Piotr Mirosz
quelle
0

Eine Ganzzahl, die mit 0 beginnt, führt ab PHP 7 zu einem schwerwiegenden Fehler, da sie möglicherweise als Oktalzeichen interpretiert wird.

Ungültige Oktalliterale

Zuvor wurden Oktalliterale, die ungültige Zahlen enthielten, stillschweigend abgeschnitten (0128 wurde als 012 angenommen). Jetzt führt ein ungültiges Oktal-Literal zu einem Analysefehler.

Vielleicht möchten Sie zuerst führende Nullen aus Ihrer Ganzzahl entfernen:

$var = ltrim($var, 0);
Lucas Bustamante
quelle