2010-10-08 4 views
5

Я новичок в PHP и пытаюсь научиться использовать PDO для подключения к тестовому MySQL db. У меня есть следующие:Выполнение подготовленной инструкции PDO с аналогичным предложением

try { 
    $db = new PDO('mysql:dbname=MYDBNAME;host=MYHOST', 'USERNAME', 'PASSWORD'); 

    $query = "select * from books where ? like '%?%'"; 
    $stmt = $db->prepare($query); 
    $stmt->execute(array($searchtype, $searchterm)); 
} catch(PDOException $e) { 
    echo 'PDOException: ' . $e->getMessage(); 
} 

Когда я пытаюсь это, я получаю следующее предупреждение: Внимание: PDOStatement :: Execute() [pdostatement.execute]: SQLSTATE [HY093]: Неверный номер параметра: количество связанных переменных не соответствует числу токенов

Когда я удаляю подобное предложение и параметр $ searchterm, он возвращает результат должным образом. Я думал, что «%?%» - не может быть законным способом создания этого запроса в двойных кавычках, поэтому я попытался сбежать », который не работал. Я огляделся в поисках решения, и обнаружили, что кто-то переехал «% и%» вниз, где $ SEARCHTERM является:

$query = "select * from books where ? like ?"; 
... 
$stmt->execute(array($searchtype, '\'%'.$searchterm.'%\'')); 

я получил тот же результат.
Любая помощь приветствуется. Благодаря!

/ ОБНОВЛЕНИЕ ****/ я нашел на примере 12 http://us3.php.net/manual/en/pdo.prepared-statements.php

Пример # 12 Invalid использование заполнитель

<?php 
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE '%?%'"); 
$stmt->execute(array($_GET['name'])); 

// Below is What they suggest is the correct way. 
// placeholder must be used in the place of the whole value 
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE ?"); 
$stmt->execute(array("%$_GET[name]%")); 
?> 

Я попробовал это, и несмотря на то, Я больше не получаю предупреждение, я не получаю никаких результатов. Однако, когда я выполняю запрос напрямую, я получу пару результатов. Есть предположения?

+0

У меня такая же проблема, как и вы, я думал, что«% », где часть структуры запроса вместо значений;) – Strae

ответ

2
$stmt->execute(array($searchtype, '\'%'.$searchterm.'%\'')); 

Это не то, как работают параметризованные запросы. Вставляемые параметры уже действуют как литеральные строки, вам не нужно добавлять разделители цитат вокруг них или избегать их (вот и все), и если вы попытаетесь, вы буквально сравниваете с строкой single-quote-searchterm-single- цитаты.

Следовательно, если вы (как я подозреваю) намереваюсь сравнить конкретный столбец с литеральной строкой, вы не определяете имя столбца. В настоящий момент вы сравниваете литеральную строку с другой литеральной строкой, поэтому она всегда будет истиной или всегда ложной независимо от данных в строке!

Так что я думаю, что вы, вероятно, имеете в виду:

$query= "SELECT * FROM books WHERE $searchtype LIKE ?"; 
$like= "%$searchterm%"; 
$stmt->execute(array($like)); 

мысли, естественно, вы должны быть очень осторожными, что $searchtype известно, хорошо, чтобы избежать SQL-инъекцию. Как правило, перед его использованием вы сравниваете его со списком допустимых имен столбцов.

(За исключением: там это способа ввода произвольных строк в имени схемы, которую можно использовать для столбца, но это раздражает, варьируется в зависимости от базы данных, и есть не стандартные спасаясь функций для него в MySQL. , вы обратная косая черта - избегайте символа backquote, кавычек и обратных косых черт и окружайте имя с помощью backquotes. В ANSI SQL вы используете двойные кавычки с двойными двойными кавычками внутри. В SQL Server вы используете квадратные скобки. Однако на самом деле вы редко меняетесь сделать что-либо из этого, потому что на самом деле вы только хотите разрешить несколько предопределенных имен столбцов.)

(Другая сторона: если вы хотите, чтобы иметь возможность разрешить $searchterm значения с буквальными процентами, подчеркиваю или слеш-так что пользователи могут искать «100%» без согласования любой строки с 100 в-вы должны использовать явный экранирующий символ, который немного утомительно :)

$query= "SELECT * FROM books WHERE $searchtype LIKE ? ESCAPE '+'"; 
$like= str_replace(array('+', '%', '_'), array('++', '+%', '+_'), $searchterm); 
$stmt->execute(array("%$like%")); 
+1

Не будет 'array ('++', '+%', '+ _')' be 'array ('\ +', '\%', '\\ _')' или даже 'array (' \% ',' \\ _ ') '(почему escape +)? (Кстати, почему Markdown здесь преобразует '\\ _' в _?) –

+0

это работает !!! но как обрезать() пространство? – user1775888

3

не добавляйте кавычки при связывании подготовленных переменных и не связывают имя столбца

$query = sprintf("select * from books where %s like ?", $searchtype); 
... 
$stmt->execute(array($searchtype, '%'.$searchterm.'%')); 
+0

Я пробовал это, и это не сработало. Я думаю, что проблема, как bobince, поставила ее в другом ответе, состоит в том, что она не принимает% в качестве подстановочного знака, а скорее буквальный «%», что не является моим намерением. – Elle

2

Проблема, которую я вижу, это если вы написали оболочку для PDO, тогда вам придется как-то обрабатывать ее отдельно. Ответ, который я нашел и любил, заключался в том, чтобы написать ваш запрос и согласовать% с параметром. т.е. столбец WHERE, такой как concat ('%',: something, '%') "

Смежные вопросы