2009-11-13 5 views
1

Может кто-то помочь мне, чтобы посмотреть, что происходит не так с этой установкойп.д.о.

Я построить запрос @sql в функции ниже, как это. Дополнительные кавычки настраиваются в массиве условий.

 $sql .= " WHERE $field = \"$value\""; 

Функция обновления pdo выполняет цикл массивов, подобный этому.

if (!is_null($conditions)) 
{ 
$cond = ' WHERE'; 
$obj = new CachingIterator(new ArrayIterator($conditions)); 
foreach($obj as $k=>$v) 
{ 
    $cond .= " $k=$v"; 
    $cond .= $obj->hasNext() ? ' AND' : ''; 
} 
} 

Моя точка, чтобы сделать то, что я не могу строить массивы со значениями без добавления слэш кавычек вокруг значений. В противном случае ошибка sql, которая бросается, заключается в том, что она является неизвестным столбцом.

Есть ли что-то другое, что я могу сделать?

Может кто-нибудь дать мне некоторые данные по этому просьбе.

редактировать: остальные выключить функцию обновления

Где я могу связать значения массива условий и иметь их выполняются также? Как я вижу это сейчас, выполняется только массив значений? Нужно ли цитировать оба массива, а затем объединить оба массива?

$obj = new CachingIterator(new ArrayIterator($values)); 

      $db = db::getInstance(); 
      $sql = "UPDATE $table SET \n"; 
      foreach($obj as $field=>$val) 
      { 
       $sql .= "$field= :$field"; 
       $sql .= $obj->hasNext() ? ',' : ''; 
       $sql .= "\n"; 
      } 

      $sql .= $cond ; 
      $stmt = $db->prepare($sql); 

      // bind de params 
      foreach($values as $k=>$v) 
      { 
       $stmt->bindParam(':'.$k, $v); 
      } 


      $stmt->execute($values); 

спасибо, Ричард

ответ

1

Не использовать addslashes(). Это неадекватный способ избежать ценностей и имеет известные ошибки безопасности.

Двойные кавычки в стандартном SQL предназначены для идентификаторов с разделителями. Используйте одиночные кавычки для строковых литералов.

Режим по умолчанию MySQL позволяет использовать взаимозаменяемые кавычки и двойные кавычки и обратные кавычки для идентификаторов с разделителями. Но я рекомендую привыкнуть использовать только одиночные кавычки для строк, потому что это делает ваш код SQL более переносимым для других поставщиков RDBMS, а также более понятным для всех, кто читает ваш код.

Вы должны использовать параметры запроса, как предлагает @Mike B. Это легко и безопаснее, чем интерполяция переменных в выражения SQL.


Вы можете использовать bindParam() или вы можете поставить $values ассоциативный массив функции execute(). Выполнение обоих является излишним.

Обратите внимание, что массив вы даете методу execute() не должен иметь : характер Предварения имени заполнителя:

$stmt = $pdo->prepare("SELECT * FROM MyTable WHERE myfield = :myfield"); 
// both of the following would work: 
$stmt->execute(array(":myfield" => $value)); 
$stmt->execute(array("myfield" => $value)); 

Также для поддержки параметров как в пункте SET и п WHERE я 'd предложить, чтобы вы отличали поля при указании имен заполнитель параметров.Таким образом, если вы ссылаетесь на одно и то же поле в обоих предложениях (один для поиска старого значения, а другой для установки нового значения), вы не будете конфликтовать.

Возможно, ":set$field" в статье SET и ":where$field" в статье WHERE.


обновление: Я тестировал следующий код. Во-первых, я использую простые массивы вместо используемого вами CachingIterator. Мне не нужно использовать метод hasNext(), так как я использую join().

$settings = array("myfield" => "value"); 
$conditions = array("id" => 1); 

$sql = "UPDATE $table SET \n"; 

Следующая демо использования array_map() и join() вместо петель. Я использую PHP 5.3.0, поэтому я могу использовать встроенные функции закрытия. Если вы используете более раннюю версию PHP, вам придется объявить функции раньше и использовать их в качестве обратных вызовов.

$sql .= join(",", 
    array_map(
     function($field) { return "$field = :set$field"; }, 
     array_keys($settings) 
    ) 
); 

if ($conditions) 
{ 
    $sql .= " WHERE " 
    . join(" AND ", 
     array_map(
      function($field) { return "$field = :where$field"; }, 
      array_keys($conditions) 
     ) 
    ); 
} 

$stmt = $db->prepare($sql); 

Я не мог заставить bindParam() работать, он всегда добавляет значение «1» вместо фактических значений в моем массиве. Так вот код, чтобы подготовить ассоциативный массив и передать его execute():

$params = array(); 
foreach ($settings as $field=>$value) { 
    $params[":set$field"] = $value; 
} 
foreach ($conditions as $field=>$value) { 
    $params[":where$field"] = $value; 
} 

$stmt->execute($params); 
+0

Спасибо, это полезно, я уже строю 4 петли в одной функции, потому что я не слишком знаком с этим. Я должен поближе рассмотреть. – Richard

+1

Вы можете закрепить свой код, используя 'array_map()' и 'join()' вместо всех этих циклов. –

+0

Спасибо, вы быстрее, я никогда не использовал эти функции, поэтому я также посмотрю на это. – Richard

4

Если вы используете PDO, то почему бы не использовать bindParam() и bindValue() методы demonstated here?

+0

спасибо, я буду смотреть на это, если это устраняет проблему – Richard

+0

Вы можете также иметь более чем один массив с полей/значений? Один для обновлений и один для условий. Потому что если я вижу это -: $ stmt-> execute ($ values); то выполняется только один массив, который связывается с параметрами? – Richard

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