Autor Zpráva
RastyAmateur
Profil
Dobrý den,

chtěl bych se zeptat na metodu prepared statements. Čerpal jsem z portálu programujte.com, a nejsem si jist, zda-li jsem to správně pochopil.

Dotaz na DB č. 1:
<?php
# Dotaz na DB
$dotaz = $mysqli->prepare("SELECT * FROM users WHERE login=? ");
$dotaz->bind_param("s",$_POST["login"]);
$dotaz->execute();

# Úprava výsledku z DB
$dotaz->bind_result($id,$jmeno,$prijmeni);
$dotaz->fetch();

# Použití v textu
echo 'Uživatel '.$jmeno.' '.$prijmeni.' má ID '.$id;

$dotaz->close();
?>

Dotaz na DB č. 1:
<?php
#Dotaz na DB (a úprava výsledku)
$dotaz = $mysqli->query("SELECT * FROM users WHERE login='".$mysqli->real_escape_string($_POST["login"])."' ")->fetch_assoc();

# Použití v textu
echo 'Uživatel '.$dotaz["jmeno"].' '.$dotaz["prijmeni"].' má ID '.$dotaz["id"];
?>

Je ten první příklad správně? Fungoval by? Jaký je rozdíl, mezi real_escape_string() a bind_param(), lépe řečeno nikde jsem nenašel, co přesně to bind_param() dělá. K čemu se používá funkce close(), když v "normálním" případě (př. č. 2) se to nedělá (nebo o tom nevím a nedělám to jen já :D )

Prostě a jednoduše bych se chtěl zeptat na nějaké podrobnosti v prepared statements. Pokud někdo ví více, než je v uvedeném odkazu...

Děkuji
juriad
Profil
RastyAmateur:
Skoro správně. Na 9. řádku bys měl mít volání metody, chybí ti tam závorky.
bind_param nahradí otazník/otazníky v připraveném dotazu za hodnotu správně escapovanou a se správným datovým typem. (Ne to nedělá, ale můžeš nad tím tak uvažovat, je to skoro ekvivalentní.)
Ten close je silně doporučený, protože připravený dotaz lze používat opakovaně (viz odkaz dole) a tedy něco málo zůstává i po posledním fetchi. mysqli_result také má metodu close, ale ta jen zahodí nevyzvednutá data z výsledku dotazu. Obvykle však použiješ všechny řádky, proto to není nutné.

Dobře je to popsané v manuálu: php.net/manual/en/mysqli.quickstart.prepared-statements.php (nevadí-li ti angličtina).
RastyAmateur
Profil
juriad:
Děkuji moc. Já to v googlu hledal jen pod heslem "bind_param", až an tom webu jsem se dozvěděl o tom celém názvu (prepared statements). V tu chvíli mě nenapadlo hledat na php.net. Jinak bych zde neotravoval :)

Takže pokud jsem to dobře pochopil, tak bind_params a otazníky se používají, protože je to rychlejší a dokonale zabezpečené, je tomu tak?

Ještě jednou děkuji :)
Jan Tvrdík
Profil
RastyAmateur:
protože je to rychlejší
To je fáma. V reálných aplikacích jsou prepared statements naopak obvykle o trochu pomalejší kvůli tomu, že to musí komunikovat s databází nadvakrát. Z toho důvodu, když v PDO „používáš“ prepared statements, tak se ve skutečnosti nepoužijí a PHP ten dotaz vyexpanduje samo.

dokonale zabezpečené
To je taky nesmysl, už proto, že nic jako dokonalé zabezpečení neexistuje. Je to lepší, než si dotazy lepit ručně, ale horší, než použít nějakou chytřejší knihovnu (ideálně spolu se statickou analýzou).

Viz také můj oblíbený komentář od Jakuba Vrány na Zdrojáku.
RastyAmateur
Profil
Tak ted nevim, jestli je lepsi to psat normalne, nebo pres PS. Mohu se zeptat, co preferujete vy?

Omlouvam se za diakritiku, pisu z tabletu.
lionel messi
Profil
RastyAmateur:
Tak ted nevim, jestli je lepsi to psat normalne, nebo pres PS. Mohu se zeptat, co preferujete vy?

Osobne uprednostňujem ručné escapovanie (z dôvodov zmienených v diskusii, ktorú odkázal Jan Tvrdík), ale som zrejme sám vojak v poli. Väčšina skúsených kolegov odporúča použitie databázovej knižnice, napr. dibi, objektívne musím uznať, že je to podstatne lepšie riešenie.
Alphard
Profil
Ten komentář je dost extrémní :-).
Já tady na diskusi skoro každému doporučuji používat alespoň dibi. Podle mě ideální knihovna, než se člověk začne rozhlížet dál, ale lze u ní i zůstat. Žádná nativní PHP extenze pro práci s databázi není dostatečně pohodlná, abych ji doporučil používat.

Ten první Jakubem uváděný bod „Nic mi nezabrání napsat $db->prepare("SELECT ... WHERE id = $_GET[id]").“ je samozřejmě možný i v dibi. Je třeba vývojáři věřit, že bude přemýšlet a takové chyby dělat nebude. U menších projektů, které dělám sám, to není problém, sám sobě věřím. Další odkazy jsou ve zmíněném komentáři.
Jan Tvrdík
Profil
RastyAmateur:
nevim, jestli je lepsi to psat normalne, nebo pres PS
Pokud tím „normálně“ máš na mysli ruční volání mysqli_real_escape_string, tak to je z hlediska bezpečnosti ještě výrazně horší řešení, než prepared statements.

Alphard:
Ten první Jakubem uváděný bod (…) je samozřejmě možný i v dibi
Jakub naráží hlavně na to, že někteří lidé trpí mylnou představou, že prepared statements poskytují dokonalé zabezpečení. V ideální případě je to možné řešit statickou analýzou, ale nevím o tom, že by pro dibi někdo něco takového napsal, ač by to asi nebylo složité.
RastyAmateur
Profil
OK, děkuji vám :)

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

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