Mysql PDO и LIKE

KorP

Новичок
Господа, никак не могу одуплить, нужно сделать запрос типа
PHP:
SELECT `id` FROM `warning` WHERE `where` = 'test' AND `time` LIKE '2012-11-01 10:31%'
напрямую в базе всё работает отлично, а вот через PDO я никак не могу его заставить работать. т.е. запрос выполняется, но ничего не возвращает. пробовал:
PHP:
$date = date("Y-m-d H:i").'%';
$stmt = Database::getInstance()->dbh->prepare("SELECT `id` FROM `warning` WHERE `where` = :tracker AND `time` LIKE :date");
$stmt->bindParam(':tracker', $tracker);
$stmt->bindParam(':date', $date, PDO::PARAM_STR);
как тут описано
где я чего не понял, подскажите плиз
 

Фанат

oncle terrible
Команда форума
на первый взгляд должно работать
не пробовал писать
PHP:
$date = '2012-11-01 10:31%';
?
Но вообще дата лайками - моветон.
 

Фанат

oncle terrible
Команда форума
c0dex
сдаётся мне, ты не понял вопроса.

KorP
у тебя же в примере выше без двоеточия работало?
А КСТАААТИ...
emulate_prepares у тебя он или офф?
если он, то поставь в офф и попробуй без лишнего двоеточия.
если офф - то поставь в он, и сделай намеренную ошибку в запросе рядом с лайком. он тебе вывалит кусок запроса на посмотреть.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Фанат
Сдается мне, ты не понял, что я написал, ибо я об эту фичу PDO гугл стер, пока понял, что не мой фейл был)

В лайке вообще плейсхолдер не пашет. Я писал об этом, чтобы заработало хоть как-то народ придумал такие вот извраты.
 

Фанат

oncle terrible
Команда форума
В лайке вообще плейсхолдер не пашет.
вот такие вещи должно быть очень стыдно писать.

KorP
про emulate_prepares я прогнал. у тебя ж именованные плейсхолдеры, то есть, они все равно по-любому парсятся пдошечкой.
Думаю, в ней всё и дело - если бы были нативные вопросеки, то всё бы нашлось.
Если не в лом - потестируй с ними (и при emulate_prepares=off )?
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Фанат
Ну раз ты у нас такой знаток, то скажи мне почему имеем следующее:

Пусть дана таблица users, там есть хренова туча полей, и есть поле pswd с паролями юзеров, у одного в пароле есть кусок строки xx177xxxxxxxxxxx, типа там лежит хэшированный пароль.

Ну так вот, имеем код (налепил на скорую руку, для примера):

PHP:
error_reporting(E_ALL);
ini_set('display_errors', 1);

try {
	$config['hostname'] = 'localhost';
	$config['username'] = 'root';
	$config['password'] = 'password';
	$config['database'] = 'test';
	$config['init'] = array(\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'');
	$config['dsn'] = 'mysql:dbname=' . $config['database'] . ';host=' . $config['hostname'];

	/** @var PDO */
	$connection = new \PDO(
		$config['dsn'], $config['username'], $config['password'], $config['init']
	);
} catch (\PDOException $e) {
	throw new Exception('Connection failed: ' . $e->getMessage());
}
Далее пишем свой код, для получения данный юзера:

PHP:
$sth = $connection->prepare("SELECT * FROM users WHERE pswd LIKE '%:placeholder%' ");
$sth->execute(array(':placeholder' => 177));
print_r($sth->fetchAll());
// Код вернет мне Array()



$sth = $connection->prepare("SELECT * FROM users WHERE pswd LIKE CONCAT('%', :placeholder, '%') ");
$sth->execute(array(':placeholder' => 177));
print_r($sth->fetchAll());
// Код вернет мне данные юзера.
Почему?
 

Фанат

oncle terrible
Команда форума
PHP:
'%:placeholder%'
- надеюсь, ты это не всерьёз написал?
или ты действительно считаешь, что это "не твой фейл"?

Кстати, должен заметить, что к вопросу ТС твои страдания всё-таки отношения не имеют. Он изначально делал правильно, и вот у него, как раз - "не его фейл".
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Фанат
объяснись уж, что в запросе не так?

Я о том, что синтаксис валиден, запрос при подстановке значения плейсхолдера руками вернет все как надо.

PS: я конечно понимаю, что влез не совсем с тем вопросом, но оно мне покоя не дает давно.
 

Semen

Семён
А не проще/правильнее вместо LIKE использовать BETWEEN
PHP:
 SELECT `id` FROM `warning` WHERE `where` = 'test' AND `time` BETWEEN '2012-11-01 10:31:00' AND '2012-11-01 10:31:59'
 

Вурдалак

Продвинутый новичок
c0dex, у тебя в первом случае обычный строковой литерал, там нет плейсхолдера. Есть зависимость от контекста. Нельзя так просто взять и заменить
Код:
:placeholder
на 177. Нельзя рассматривать SQL-шаблон как самую примитивную строку, в которой мы
Код:
$query = str_replace(':placeholder', escape($value), $queryTemplate);
делаем, так ты как раз бы получил уязвимости.
 

Фанат

oncle terrible
Команда форума
Да с какой радости он валиден-то?
Ты не понимаешь принципиального смысла плейсхолдеров.
Это не тупо подстановка по типу printf-a. Оно в таком варианте в принципе не будет работать, потому что невозможно защитить данные.
Плейсхолдер - это переменная в запросе. Он может представлять собой только целый кусок данных, а не их часть.
Лайк в качестве параметра принимает строку. "процентики" - это часть строки, а не часть оператора LIKE.
Ты должен сформировать строку данных, и эту строку передать с помощью плейсхолдера в запрос.

Точно так же ты не можешь забиндить выражение "0,10" для LIKE. потому что здесь ДВЕ переменные, и они должны биндиться отдельно.
По ссылке, которую ты дал, это же как раз и объясняется.
 

Redjik

Джедай-мастер
c0dex
wildcard надо в подстановку пихать
PHP:
$sth->execute(array(':placeholder' => '%177%'));
 

Фанат

oncle terrible
Команда форума
Redjik
"как надо" он и сам вас научит.
он спрашивает, почему.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
У меня и был вопрос как раз о том,
Нельзя рассматривать SQL-шаблон как самую примитивную строку
Мне это было неочевидно, так как я надеялся, что данный синтаксис должен по логике прокатить. Ибо кардинальных отличий в самом запросе нет.

Про замечание Redjik о
wildcard надо в подстановку пихать
я в курсе.
 

Фанат

oncle terrible
Команда форума
Ибо кардинальных отличий в самом запросе нет.
Не сочти за наезд, но отличий нет только если рассматривать запрос с ламерской позиции "пихаем всё что под руку попало (и искейпим "вредные" символы)".
Если же рассматривать запрос по частям, отделяя данные от кода, то отличия есть.

Агументом оператора лайк является строковый литерал. У строкового литерала есть простые правила форматирования:
- он должен быть ограничен кавычками
- внутре должны быть прослешены спецсимволы.

Следовательно, если мы хотим делать всё правильно, мы должны помещать в запрос уже отформатированный литерал. Целиком.
А не собирать его в запросе. Потому что такая сборка в итоге и ведет к инъекциям.
Именно поэтому разница есть
PHP:
:placeholder
- законный элемент синтаксиса. В режиме эмуляции будет трансформирован в строку в соответствии с вышеперечисленными правилами.
PHP:
'%:placeholder%'
- литерал, собранный из огрызков. Трансформировать в строку в соответствии с правилами невозможно

но дело всё равно даже не в этом
А в том, что плейсхолдер, как объяснено по твоей ссылке, не может являться частью литерала.
плейсхолдер - это отдельный элемент синтаксиса запроса. Ну как знак "+" в ПХП.
Если он стоит просто в коде - то это оператор "плюс".
Но если он стоит внутри строки - это просто символ!
Так и здесь:
Если плейсхолдер является самостоятельной частью запроса - это плейсхолдер. Если же частью строки - это всего лишь часть строки безо всякого специального значения.
обратно разница есть.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Спасибо, вопрос снят)
 
Сверху