Autor Zpráva
hellicos
Profil *
Dobrý den jsem na začátku s učením se s PHP, ale při svojí tvorbě jsem našel jednu věc kterou nevím jak udělat. Mám proměnou $s, která obshuje hodnotu 0 nebo 1 podle toho, jestli je uživatel zablokovaný nebo ne. Tvořím tabulku se seznamem uživatelů a chtěl bych je mít filtrované podle toho, co je napsané v URL. Pokud bude jen example.com, zobrazí se všichni uživatelé, pokud bude example.com?s=0, zobrazí se pouze zablokovaní uživatelé a pokud bude example.com?s=1, zobrazí se pouze aktivní uživatelé. První a poslední funguje podle mých představ, ale example.com?s=0 mi zobrazí všechny uživatele. Kdy by mohl být prolém?

$s = $_GET['s'];
if (empty($s)){$podminkas = "";} else {$podminkas = "WHERE stav = " .$s;};
$sql = "SELECT * FROM uzivatele $podminkas ORDER BY id DESC";
Keeehi
Profil
hellicos:
Problém je v empty($s). Ono totiž
empty("0")  === true
Vím, je to takové intuitivní, že neprázdný řetězec je funkcí empty vyhodnocen jako true, ale tak to bohužel je. V PHP je to spoustu a spoustu let a tudíž odstranit se to nedá. Ono vůbec to automatické přetypování je dost magické a často může být zdrojem chyb v programech. Nicméně, po nějaké době si těch pár zvláštností zapamatuješ.
Jak to optavit? Použil bych isset.
if (!isset($_GET['s'])) {
    $podminkas = "";
} else {
    $podminkas = "WHERE stav = " .$_GET['s'];
}
$sql = "SELECT * FROM uzivatele $podminkas ORDER BY id DESC";
I když toto je už funkční, není to bezpečné. Ono totiž do té url adresy se nemusí přidat jen 0 nebo 1, ale někdo by tom mohl připsat třeba kus SQL kódu. Když se to pak spojí s tím zbytkem a celé pošle do databáze, tak si umíš představit co to může nadělat za paseku. Téhle zranitelnosti se říká SQL Injection. Je třeba tedy zajistit že to co tam připojuješ je v tvém případě opravdu jen číslo. Toho se dá lehce docílit vynuceným přetypováním.
    $podminkas = "WHERE stav = " .(int)$_GET['s'];
Kdyby šlo o řetězec tak by bylo potřeba něco takového
mysqli_real_escape_string($link, $_GET['s'])

S trochou magie se to celé dá napsat jako
$sql = "SELECT * FROM uzivatele".(isset($_GET['s']) ? " WHERE stav = ".(int)$_GET['s'] : "")." ORDER BY id DESC";
hellicos
Profil *
Děkuji za odpověď a kód, který vyřešil můj problém. Teď se tabulka filtruje správně. Když už mám založené tohle vlákno, chtěl bych se ještě zeptat na jednu věc:

Když už mi správně funguje filtrování obsahu podle zadaného parametru s, rád bych měl při každé verzi jiný nadpis stránky - tj. pokud example.com?s=1, nadpis bude aktivní uživatelé, pokud bude example.com?s=0, nadpis bude neaktivní uživatelé a pokud bude pouze example.com bez zadané hodnoty s, nadpis bude všichni uživatelé.

Zkoušel jsem modifikovat Váš kód na:

if (!isset($_GET['s'])) {
    $nadpis = "všichni uživatelé";
}
if ((int)$_GET['s'] = "0") {
$nadpis = "neaktivní uživatelé";}
if ((int)$_GET['s'] = "1") {
$nadpis = "aktivní uživatelé";}

Nadpis je ale pokaždé aktivní uživatelé. Původně jsem si myslel, že php bere hodnotu 1 jako true - tj. pokud je zadaná hodnota s (jakákoliv), pak automaticky $nadpis = "aktivní uživatelé"; , ale pak jsem postřehl, že je nadpis aktivní uživatelé i v případě, že není zadáno s. Jak to tedy funguje? Lze nějakým způsobem měnit nadpis při filtru tabulky?
Kajman
Profil
K porovnání slouží dvě nebo tři rovnítka. Jedno je přiřazení. Také v tomto případě používejte elseif.
Keeehi
Profil
Dalším tipem je to, že zde je přetypování zbytečné. V části s SQL dotazem je to potřeba ale tady je to zbytečné.
if (!isset($_GET['s'])) {
    $nadpis = "všichni uživatelé";
} elseif ($_GET['s'] === "1") {
    $nadpis = "aktivní uživatelé";
} else {
    $nadpis = "neaktivní uživatelé";
}

Mimochodem, na porovnání jsem použil tři rovnítka a ne jen dvě. Ta kontrolují i datový typ a tak se u nich neprovádí automatické přetypování. Jelikož automatickou konverzi typů nechceš prakticky nikdy, zvykni si už od začátku používat na porovnávání tři. Do budoucna ti to ušetří určitě pár chyb.

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0