абстракция базы данных pdo - PullRequest
1 голос
/ 13 ноября 2009

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

Я строю запрос @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 в том, что это неизвестный столбец.

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

Может, кто-нибудь подскажет, пожалуйста.

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

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

$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 );

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

Ответы [ 2 ]

4 голосов
/ 13 ноября 2009

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

1 голос
/ 13 ноября 2009

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

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

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

Вы должны использовать параметры запроса, как подсказывает @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, я бы посоветовал вам различать поля при указании имен заполнителей параметров. Таким образом, если вы ссылаетесь на одно и то же поле в обоих пунктах (одно для поиска старого значения, а другое для установки нового значения), вы не будете конфликтовать.

Возможно ":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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...