2012-06-13 5 views
0

Я пытаюсь использовать следующий код для поиска базы данных с использованием слов в поле поиска.Предупреждение: PDOStatement :: execute() [pdostatement.execute]: SQLSTATE [HY093]: Неверный номер параметра:

По какой-то причине, я получаю следующую ошибку

Предупреждение: PDOStatement :: bindValue() [pdostatement.bindvalue]: SQLSTATE [HY093]: Неверный номер параметра: Столбцы/Параметры являются 1- основанный в ..

Вот код функции:

// Retrieve search results 
    function retrieve_search_posts($searchfield){ 
     //test the connection 
     try{ 
      //connect to the database 
      $dbh = new PDO("mysql:host=localhost;dbname=mjbox","root", "usbw"); 
     //if there is an error catch it here 
     } catch(PDOException $e) { 
      //display the error 
      echo $e->getMessage(); 

     } 

     $where = array(); 

     $words = preg_split('/[\s]+/',$searchfield); 

     $total_words = count($searchfield); 

     for($i = 0; $i < count($words); $i++){ 

      $where[] .= "`post_title` LIKE ?"; 

     } 

     $where_string = implode(" OR ", $where); 

     $query = " 
           SELECT p.post_id, post_year, post_desc, post_title, post_date, img_file_name, p.cat_id 
           FROM mjbox_posts p 
           JOIN mjbox_images i 
           ON  i.post_id = p.post_id 
             AND i.cat_id = p.cat_id 
             AND i.img_is_thumb = 1 
             AND post_active = 1 
           WHERE post_title LIKE ? 
           ORDER BY post_date 
           DESC"; 

     $stmt = $dbh->prepare($query); 

     foreach($words AS $index => $word){ 
      $stmt->bindValue($index, $word, PDO::PARAM_STR); 
     } 

     $stmt->execute(); 

     $searcharray = $stmt->fetchAll(PDO::FETCH_ASSOC); 

     return $searcharray; 
    } 

Что я сделал неправильно с использовать появившееся сообщение об ошибке?

+0

Вы подтвердили, что thaat «$ searchfield» имеет значение? потому что сообщение об ошибке точно говорит о несоответствии параметров. – BlueBird

+0

Ваш отказ от использования '$ where_string', поэтому' $ query' имеет только 1 привязку, но '$ words' может содержать более 1 –

ответ

1

Во-первых, вы не использовали строка ...OR LIKE статьи, которые вы тщательно сконструировали в цикле.

Во-вторых, по мере того как ошибка говорит, подготовленные параметры оператора являются 1-индексированными, тогда как ваш массив индексируется 0. Вам нужно сместить все индексы в массиве до 1, чтобы заставить его работать с вашим текущим foreach или добавить 1 к ним во время цикла.

Попробуйте вместо этого:

function retrieve_search_posts($searchfield){ 
    //test the connection 
    try{ 
     //connect to the database 
     $dbh = new PDO("mysql:host=localhost;dbname=mjbox","root", "usbw"); 
    //if there is an error catch it here 
    } catch(PDOException $e) { 
     //display the error 
     echo $e->getMessage(); 

    } 

    $words = preg_split('/[\s]+/',$searchfield); 

    // Easy way to 1-index a 0-indexed array 
    array_unshift($words, ''); 
    unset($words[0]); 

    // Never used and meaningless - $searchfield is a string 
    // $total_words = count($searchfield); 

    // Tidier and more resilient than the loop 
    $where_string = implode(" OR ", array_fill(0, count($words), "`post_title` LIKE ?")); 

    $query = " 
     SELECT p.post_id, post_year, post_desc, post_title, post_date, img_file_name, p.cat_id 
     FROM mjbox_posts p 
     JOIN mjbox_images i 
     ON  i.post_id = p.post_id 
       AND i.cat_id = p.cat_id 
       AND i.img_is_thumb = 1 
       AND post_active = 1 
     WHERE $where_string 
     ORDER BY post_date 
     DESC 
    "; 

    $stmt = $dbh->prepare($query); 

    foreach ($words AS $index => $word){ 
     // You may want to use "%$word%" or similar below, as it is the LIKE 
     // keyword in your query is doing nothing and you might as well use = 
     $stmt->bindValue($index, $word, PDO::PARAM_STR); 
    } 

    // Handle the potential error here! 
    $stmt->execute(); 

    return $stmt->fetchAll(PDO::FETCH_ASSOC); 

} 
+0

Спасибо, я понятия не имел, что PDO начинается с [1] .. код отлично работает. – crm

+0

Итак, вы использовали 'array_shift' и' unset' для перемещения каждого значения в 1 место в массиве и затем удалили новый пустой [0] ключ? – crm

+2

Да точно. Это простой подход, но он работает. Если вам нужно сделать это в нескольких местах вашего кода, вы можете обернуть его в функцию типа 'function one_index_array ($ array) {array_unshift ($ array, ''); снята с охраны ($ массив [0]); return $ array; } '- тогда вы можете просто сделать' $ words = one_index_array (preg_split ('/ [\ s] + /', $ searchfield)); ' – DaveRandom

1

"1 на основе" не очень дружелюбным сообщение об ошибке

Википедия: http://en.wikipedia.org/wiki/Array_data_type#Index_origin

1 на основе = минимальное значение равно 1, так что 0 (первое значение в массиве php/c) недействительно

foreach($words AS $index => $word){ 
     $stmt->bindValue($index+1, $word, PDO::PARAM_STR); 
    } 
+0

спасибо, но почему это было бы на 1 основе? – crm

+1

@crm В PHP индексированные массивы, возвращаемые нативными функциями, обычно нулевые индексы (т. Е. Ключ первого элемента равен '0'). Как это часто бывает в случае с PHP, когда были подготовлены заявления PDO, разработчики решили проигнорировать это соглашение и вместо этого использовать маркеры с 1 индексом, нарушив то, что вы пытались сделать, что является очевидным подходом и должно быть выполнено с помощью прав. Вы можете легко перенести индексы в массив, см. Мой ответ. – DaveRandom

+0

Ярмарка вопрос. Начав писать умозрительный ответ, но решил удалить его, потому что он был просто бессвязным - я понятия не имею –

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