Backslash (slash to
/ 
) znika podczas parsowania zapytania SQL dokładnie w taki sam sposób, jak to się dzieje w każdym cywilizowanym języku programowania. Popatrz na PHP. Spróbuj wyświetlić:
<?php
?>
Tu też backslash znika, ponieważ on pełni jedynie rolę pomocniczą w składni: pozwala wpisać apostrof tak, żeby nie został on przez parser zinterpretowany jako koniec ciągu tekstowego. Dokładnie to samo masz w zapytaniu:
Kod
$pdo->query('SELECT * FROM foo WHERE title=\'Tekst \\' tekst\'');
Teraz gdy PHP bierze się za przetwarzanie, na własne potrzeby zabiera pierwszy backslash i do bazy idzie:
Kod
SELECT * FROM foo WHERE title='Tekst \' tekst'
Na identycznej zasadzie MySQL zabiera drugi backslash i wie, że ma porównać pole z tekstem
Kod
Tekst ' Tekst
Jeśli chodzi o obawy, to masz się czego bać, ale z trochę innego powodu, niż sądzisz. Otóż kiedyś ktoś "mądry" wymyślił w PHP tzw. "magic quotes". Polega to w mocnym skrócie na tym, że wszystkie dane, które przychodzą do skryptu metodą POST, GET, jako ciastka itd. są domyślnie escape'owane (tzn. dodawany jest przed niebezpiecznymi znakami backslash). Jeśli więc wysłaliśmy tekst
Foo ' bar, to skrypt już z definicji będzie operować na ciągu
Foo \' bar. Jeśli teraz skrypt też we własnym zakresie escape'uje potrzebne dane, to w bazie powstanie syf, gdyż poleci tam:
Foo \\' bar. Z kolei jeśli magiczne cytaty są wyłączone, a skrypt nie escape'uje danych, otrzymujemy dziurę bezpieczeństwa i narażamy wszystkie zapytania na ataki typu SQL Injection.
Osobiście polecam pisać skrypt tak, jakby magiczne cytaty były wyłączone, gdyż takie jest obecnie domyślne ustawienie i będą one wycofywane. Na początku skryptu umieszczamy jedynie prosty filtr, który w przypadku ich włączenia zniweluje ich efekty, tj. skasuje nadmiarowe slashe. Ponadto, zapomnij o funkcjach typu
mysql_ i
mysqli_. Jest PDO, jest tam wbudowana możliwość podpinania parametrów pod zapytanie i one są wtedy automatycznie escape'owane, gdy zachodzi taka potrzeba, zależnie od ustawień konfiguracji:
<?php
$stmt = $pdo->prepare('SELECT * FROM foo WHERE title = :title');
$stmt->bindValue(':title', 'To jest tytuł', PDO::PARAM_STR);
$stmt->execute();
?>