Já tedy v dokumenatci MySQLi vidím něco úplně jiného. Když vezmu stránky postupně podle obsahu, první stránka, kde se objevují parametrizované dotazy, je Executing statements . Parametry INSERT
u jsou tam přímo součástí příkazu, což v reálné aplikaci nedává vůbec žádný smysl – a vše je tam pomocí query
, o prepare
na té stránce není jediná zmínka. Evidentně i autoři PHP považují prepare
za něco speciálního, co se nepoužívá pro běžné vykonávání příkazů. Následuje kapitola Prepared Statements, kde se hned v druhé větě píše, že se to používá pro opakované opakované vykonávání stejných příkazů z důvodu vysoké efektivity. Pokud to čte začátečník, správně si řekne, že optimalizace zatím není nic pro něj, stejně bude zatím používat jen jednoduché příkazy. Následuje kapitola o uložených procedurách, kde jsou všechny parametry opět natvrdo součástí SQL příkazu. prepare
je tam uvedené jednou – bez parametrů. Následuje několik dalších kapitol s query
a parametry, které jsou natvrdo v SQL příkazu, takže příklady, které nemají nic společného s reálnými aplikacemi – a pokud se jimi někdo inspiruje, logicky dospěje k tomu, že ty konstantní parametry akorát nahradí odkazem na proměnnou. Přitom jinak jsou ty příklady vzorové, všude se testují návratové kódy – tak, jak by ten kód měl vypadat v reálné aplikaci. Kapitoly o instalaci a podobné asi můžeme přeskočit, následuje už dříve odkazovaná stránka MySQLi extension basic examples, kde o prepare
opět není ani zmínka, naopak se obsah proměnné vkládá přímo do SQL příkazu. Přitom tohle je ta stránka, odkud začne každý, kdo jenom rychle potřebuje vědět, jak se volají dotazy do databáze. A většina programátorů u téhle stránky taky skončí, protože podle ní napíšou svůj kód, vyzkouší, kód jim vrátí správná data, a tím to pro ně končí, nebudou mít důvod číst něco dalšího – vždyť jim to přece funguje. Zpět k tomu příkladu – na začátku v komentáři sice je zmínka o SQL injection a že se kvůli tomu přetypovává na int
, ale kdo ten komentář bude číst? A i když si ho někdo přečte – „Handling all of this goes beyond the scope of this simple example.“ Takže SQL injection a bezpečnost je něco pro pokročilé, začátečníci o tom nepotřebují vědět nic. Když pak někdo tenhle příklad vezme, akorát místo čísla bude potřebovat použít jako parametr text, hned má přímo ukázkový kód s SQL injection – aniž by vůbec tušil, že je něco špatně.
Autoři PHP zjevně považují prepared statements za něco pokročilého, co si najde ten, koho to opravdu zajímá. Zároveň PHP neumí bindování proměnných jinak, než s prepared statements. PHP zkrátka programátorům doporučuje nástroj, který je (zbytečně) náchylný k SQL injection, a navíc tuhle vážnou bezpečnostní hrozbu odbude poznámkou pro zasvěcené, místo aby tam byl výrazný červený nápis s vykřičníky, že takhle se to dělat nemůže. Tohle prostě je problém platformy PHP a vysvětluje to, proč je tolik PHP aplikací napadnutelných přes SQL injection.
Interní implementace prepared statements v MySQL v tom nemusí hrát žádnou roli, parametrizované dotazy s bindováním proměnných není vůbec nutné implementovat přes prepared statements – klidně může dvouparametrická funkce query()
interně pomocí escapování skládat parametry do textového dotazu. Sice považuju escapování za hack, ale pořád je to milionkrát bezpečnější, když to ta funkce bude dělat takhle, než nechávat to na tom, jestli programátor vůbec tuší něco o SQL injection a vzpomene si, že to má nějak řešit.