А я и не знал... Правда там на mysql пример. https://habrahabr.ru/post/142599/ --- Добавлено --- вообще у mysqli экранирование странно работает. --- Добавлено --- А вот она где собачка зарыта... Из доки: Код (Text): Набор символов должен быть задан либо на стороне сервера, либо с помощью API функции mysqli_set_charset(). В противном случае mysqli_real_escape_string() работать не будет. --- Добавлено --- Капец mysqli... Реально бесполезное экранирование пришлось писать аж вот так PHP: foreach ($array As $key => $value) { $stringIns[] = "`".$this->dbConnect->real_escape_string($key)."`"; $stringValues[] = "'".$this->dbConnect->real_escape_string($value)."'"; }
некоторые люди всегда найдут способ ошибиться. здесь трудности перевода "set A to affect B" почему-то перевели как "сделайте А, иначе B работать не будет" что кагбэ искажает изначальный смысл. имелось в виду, что данная настройка влияет на указанную функцию. но поздняк, данный вариант перевода расползся по рунету. фактически соединению всегда сопоставлен какой-то набор символов, как правило, если ничего не укажешь на клиенте, то будет использован latin1 (он же cp1250). известно, что в старых версиях MySQL был баг для некоторых азиатских мультибайтных кодировок — бала возможна атака с имитацией апострофа внутри "длинного" символа. https://stackoverflow.com/a/12118602/272885 --- Добавлено --- указывать кодировку соединения надо, чтобы данные в базе были верными. в этом смысл функции.
на пдо у меня выглядит это вот так: PHP: static::$db = new \PDO("mysql:host=".$db['host'].";port=".$db['port'].";dbname=".$db['dbname'].";charset=".$db['charset'], $db['username'], $db['password']); У меня при создании подключение устанавливается кодировка в пдо, а в mysqli пришлось сделать вот так, PHP: $this->dbConnect = DB::connect(); $this->dbConnect->set_charset("utf8"); --- Добавлено --- но суть темы вот в этом --- Добавлено --- но один фиг вот эта хрень: Код (Text): ->real_escape_string($value) работает не так как quote у pdo --- Добавлено --- она не добавляет '' ковыки в начале и конце строки --- Добавлено --- я скок прогаю на пыхе всё время юзаю pdo никогда не отдавал предпочтений mysqli... --- Добавлено --- и вообще не трогал его никогда оббегал стороной за 300 км... А тут пришлось Эх... А он работает не так, методы другие ещё и не так работают, эх, пришлось доку штудировать...
Буратина, почему "бесполезное"?! Если нет ни экранирования, ни плейсхолдеров, то возможна инъекция. Так что полезное. Было бы удобнее апострофы оставить в теле запроса, а не в переменной. Пример из руководства по функции PHP: $city = "'s Hertogenbosch"; $city = $mysqli->real_escape_string($city); /* this query with escaped $city will work */ if ($mysqli->query("INSERT into myCity (Name) VALUES ('$city')")) { printf("%d Row inserted.\n", $mysqli->affected_rows); }
Потому что: PDO::quote - Мне больше по душе. Логика такова апострофы раставляет сама (помимо экранирования). Значит метод quote полезный а тот бесполезный. Но сори там такого нет. Поэтому получите распишитесь. --- Добавлено --- Так между прочем классный мультик. --- Добавлено --- Любил его в детстве
P.S. в pdo::quote нет нужды, т.к. в pdo нормальные плейсхолдеры есть и с ними всё чётко отрабатывает без добавления апострофов! из доки: PHP: $sql = 'SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour'; $sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY)); $sth->execute(array(':calories' => 150, ':colour' => 'red')); $red = $sth->fetchAll(); $sth->execute(array(':calories' => 175, ':colour' => 'yellow')); $yellow = $sth->fetchAll();
Зачем переместили тему я не чего не спрашивал. --- Добавлено --- Просто зачем? --- Добавлено --- Я вообще не понимаю зачем ты это пишешь потому что я это прекрасно и без тебя в документации прочёл. --- Добавлено ---
Mysqli supports prepared statements with "?" placeholders for parameters. PDO supports both "?" placeholders and also named placeholders, like ":columnName". Mysqli requires that you use a function to bind each parameter value to the prepared statement. PDO also allows you to simply pass an array of parameter values as you execute the prepared statement. я помню как-то пытался, но bind_result убил мои надежды выглядело так, что кто-то специально придумал эту "фишку" чтобы заставить программистов страдать. --- Добавлено --- @pinokio А кто сказал, что без вопроса туда нельзя? Успокойся уже. За тебя решают другие.
да ты что? А вот это: PHP: public function where($where) { $stringIns = []; foreach ($where As $key => $value) { $stringIns[] = sprintf('%s=%s', $key, $this->dbConnect->quote($value)); } $this->where = implode(' AND ', $stringIns); $this->where = trim($this->where, ' AND '); return $this; } --- Добавлено --- И как бы писать bind param как то не особо хочется через quote как то более простая реализация --- Добавлено --- не спорю при написании конкретного запроса чёткая вещь.
А то что реализация в три строчки кода. --- Добавлено --- Чтобы получить массив который передаётся в execute Надо сделать следующее: PHP: $arr = []; foreach ($where As $key => $value) { $arr[':'.$key] = $value; } $sth->execute(array(':calories' => 150, ':colour' => 'red')); Тут как бы тоже три строчки, но мне не нравится вот этот костыль Код (Text): $arr[':'.$key] Код (Text): ':'. --- Добавлено --- Выглядит страшно.
я уже где-то на форуме писал недавно, что построитель запросов (от Laravel) идеально подходит построения запросов. внезапно™ ни одной подстановки переменной прямо в тело запроса не понадобится. потому что там вообще SQL запрос не торчит наружу. а раз нет текста запроса, то и некуда и незачем подставлять эти экранированные переменные. с этим не накосячить.
конкатенация в ключе массива.. Не хочу. Не буду. Не заставляйте меня это делать. )) --- Добавлено --- Это как ?
я пересказывать доки ларавель не буду. to google "laravel query builder" код твой просто кошмар. смех и грех.
вызывать sprintf чтобы добавить один символ между двух строк? что должен делать trim(…, ' AND ') после implode(' AND '…) ты видимо не в курсе как работает implode. видно что это результат копи-пасты. и этот блин человек тут качает права, в раздел профи лезет, ругает потенциальных заказчиков, грубит модераторам. ты неадекват, Лёня. нестыдно чего-то не знать. стыдно выдавать себя за крутого чтобы очевидно потом обосраться. и говорить "нет я не обосрался, это не говно". другого и быть не могло.
Хорошо возьми этот вставь себе и добавь туда массив такого хар-ра [''] и отправь его туда предварительно убери Трим --- Добавлено --- Вставь метод* --- Добавлено --- Не добавь а передай так правильнее сказать
смешно, да. давай ты вставишь себе и уберёшь. это был бесплатный урок. а пока я оцениваю твоё упорство в 1 штрафной балл.
Внезапно, но экранирование отвечает за...экранирование спецсимволов внутри стоки, а не за добавление кавычек. Когда я передаю строку на экранирование, я ожидаю получить ее модифицированный эквивалент, где ряд символов заменен на их экранированные версии, а не ее строку с добавленными значимыми символами, которые я не просил. Бред. И не unix-way. --- Добавлено --- PANIC! ALARM! ALERT! WARNING! А МУЖИКИ-ТО И НЕ ЗНАЮТ! Статья от 2012 года. Сейчас 2017. И запрос падает с ошибкой, если в нем есть строковое значение, не обрамленное в кавычки. Потому как такое значение по умолчанию расценивается как имя столбца/алиаса/переменной/чего-нибудь, но, так как оно отсутствует в скоупе запроса, запрос падает. --- Добавлено --- Поправьте, если ошибаюсь.
да всё верно. собственно та статья на хабре о том, что пользовательскому вводу не надо верить + что неправильное использование функций порождает уязвимости, а не о том, что экранирование буквально "бесполезно". )))
я сегодня как раз с этим столкнулся.. . решил написать обертку... еще не доделал.. но теперь работа с mysqli и плейсхолдерами выглядит так Код (Text): public function getByIds(array $ids) { $result = $this->dbQuery( 'SELECT * FROM {db_prefix}site WHERE data1int IN({array_int:ids}) AND data1int = {int:id}', array( 'ids' => [1,2,3,4,5,6,7,8,9], 'id' => 2342, )); $items = []; if ($this->dbNumRows($result) > 0) { while ($row = $this->dbFetchAssoc($result)) { $items[] = $row; } } $this->dbFreeResult($result); return $items; } это пример)) но задумка такая)) еще обертку не полностью доделал..