PHP: Pozor na zákeřnou funkci filter_var() a FILTER_VALIDATE_INT. Provádíte validaci nulových hodnot (a nejen těch) správně?

by Zdeněk Večeřa 0 Comments

Chceme ověřit, jestli vstup od uživatele je opravdu jakákoliv hodnota integer. Očekáváme tedy celé záporné číslo, celé kladné číslo nebo nulu. Pokud pro validaci celočíselných hodnot (FILTER_VALIDATE_INT) používáme PHP funkci filter_var(), můžeme se při nevhodně použité podmínce dostat do problémů s nulou.

Mějme následující vlastní validační funkci (předem upozorňuji, že je chybná, takže ji NEPOUŽÍVEJTE):

function valid_integer($number)
{
    if (filter_var($number, FILTER_VALIDATE_INT)) {
        return 1;
    } else {
        return 0;
    }
}

Když funkci filter_var() předáme vstupní hodnotu, očekáváme, že nám vrátí hodnotu 1, pokud bude hodnota celé číslo a ve všech ostatních případech vrátí hodnotu 0.

Podívejme se, co vypíše u jednotlivých volání s různými hodnotami:

echo valid_integer(2020); // 1
echo valid_integer(1); // 1
echo valid_integer(0); // 0, což je špatně, protože nula je integer
echo valid_integer(10.5); // 0
echo valid_integer('2020'); // 1
echo valid_integer('1'); // 1
echo valid_integer('0'); // 0, což je špatně, protože nula je integer
echo valid_integer('10.5'); // 0
echo valid_integer('ahoj'); // 0

Funkce filter_var() vrací filtrovaná data, nebo FALSE, když filtr selže. Problém je tedy v naší podmínce. Upravme ji proto takto:

function valid_integer($value)
{
    if (filter_var($value, FILTER_VALIDATE_INT) !== false) {
        return 1;
    } else {
        return 0;
    }
}

Nyní již funkce vrátí očekávané výsledky:

echo valid_integer(2020); // 1
echo valid_integer(1); // 1
echo valid_integer(0); // 1
echo valid_integer(10.5); // 0
echo valid_integer('2020'); // 1
echo valid_integer('1'); // 1
echo valid_integer('0'); // 1
echo valid_integer('10.5'); // 0
echo valid_integer('ahoj'); // 0

Validační funkce filter_var() respektuje netypovost PHP jazyka

Pokud se k nám dostane hodnota z odeslaného formuláře, číslo může být jako součást řetězce. Nebo proměnnou ořezáváme pomocí funkce trim(). V zápisu kódu je to ekvivalentní tomuto:

$value = "10";

Což je trochu něco jiného než následující čistě číselná hodnota:

$value = 10;

PHP je netypový jazyk, takže nerozlišuje mezi výše uvedenými zápisy. Se všemi výhodami a nevýhodami s tím spojenými.

Pokud pro validace použijeme filter_var(), netypovost je dle očekávání dodržena a obě hodnoty jsou vyhodnoceny jako celé číslo. 

Kdybychom ale pro validaci použili funkce is_int() nebo is_float(), tak v případě číselné hodnoty předané jako řetězec máme problém. Obě funkce totiž kontrolují datový typ.

Vedle toho funkce is_numeric() ověřuje, jestli je hodnota jakékoliv číslo (celé, desetinné atd.), ale dodržuje netypovost jazyka, takže ji můžete použít jak pro ověření čistě číselných hodnot, tak i číselných řetězců.

Validační funkce filter_var() je tu s námi již od PHP 5.2.0, tedy téměř čtrnáct let, přesto se jí spousta programátorů vyhýbá. Což je škoda.

Leave a reply

Your email address will not be published.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Tato stránka používá Akismet k omezení spamu. Podívejte se, jak vaše data z komentářů zpracováváme..