Мой запрос к базе данных продолжает устанавливать все столбцы на одно и то же значение в MySQL - PullRequest
2 голосов
/ 05 февраля 2010

Вот мой метод обновления для Kohana 3.

public function update($type, $id, $updates) {
        $info = $this->getInfo($type);
        $dbTable = $info['table'];

        $updatesKeysToValues = array();

        var_dump($updates);

        foreach($updates as $key => $value) {
            // if the value is null or the key isnt set for this, don't update!
            if ($value === null OR ! isset($info['columnsToUpdateData'][$key])) continue;
            $updatesKeyToValues[] = "`$key` = :$key";

        }

        $updatesKeyToValues = implode(', ', $updatesKeyToValues);

        $query = 'UPDATE `' . $dbTable . '` SET ' . $updatesKeyToValues . ' WHERE id = :id LIMIT 1' ; 

        echo $query;

        $dbQuery = DB::query(Database::UPDATE, $query);

        foreach($updates as $key => $value) {
                echo "$key === $value\n<br>";
                $dbQuery->bind(':' . $key, $value);
         }

        $success = $dbQuery->bind(':id', $id)    
                        ->execute();    

        var_dump($success);

    }

Во время каждого var_dump() и echo данные в порядке.Ничто не говорит о том, почему это происходит.

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

Кажется, я не могу понять это, не так ли?Большое спасибо за ваше время.

ОБНОВЛЕНИЕ

Мне только что пришла в голову мысль, действительны ли подчеркивания в именах параметров в запросе?

ДРУГОЕ ОБНОВЛЕНИЕ

Вот вывод echo $query

UPDATE `personnel` SET `first_name` = :first_name, `last_name` = :last_name, `email` = :email WHERE id = :id LIMIT 1

Я также разработал этот метод привязки нескольких параметров к запросу тоже.Я никогда не делал это раньше, но я предполагал, что это сработает.В Kohana 2.x я всегда использовал $bindings[] = 'tom@jones.com' и т. Д., Но, насколько я могу судить, новая Kohana не принимает массив.

FINAL UPDATE

Спасибо всем, я думаю, что это передается по ссылке.Я обошел его, установив $updates[$key]

Похоже, я мог бы также использовать метод param() вместо bind. Просмотр источника

Ответы [ 3 ]

4 голосов
/ 05 февраля 2010

Я не знаю, какой уровень доступа к данным вы используете здесь, но я предполагаю, что это:

foreach($updates as $key => $value) {
    $dbQuery->bind(':' . $key, $value);
}

может делать что-то действительно обманчивое: брать параметры по ссылке.

Итак, что произойдет, так как $value является реальной переменной, функция bind() получает ссылку на нее и запоминает, что именно эта переменная - не текущее значение переменной - то, что она будет привязана к данному параметру. Затем вы в следующий раз идете по циклу foreach, и у нас возникает классическая проблема цикла в C-подобных языках: вы не получаете новый экземпляр $key и $value, вы фактически меняете существующие переменные, которые у вас уже были, как и для стандартного цикла for ($i= 0....

Итак, когда приходит время выполнить запрос, какой параметр :a? Это текущее значение $value, последнее в цикле. Какой параметр :b? Такой же. И так далее.

Я знаю, что некоторые интерфейсы параметризации PHP делают это (mysqli, я думаю?), Но в целом получение параметров по ссылке очень вероятно, что IMO приведет к нежелательному поведению, подобному этому, и я, конечно, считаю, что это совершенно неуместно для привязки параметров такой интерфейс.

ETA: только что посмотрел query.php по ссылке, которую вы разместили на комментарий Джона. Да. Вздох. Он принимает параметры по ссылке. Как ужасно.

4 голосов
/ 05 февраля 2010

функция привязки использует ссылку на ваше значение $

public function bind($param, & $var)
{
 // Bind a value to a variable
    $this->_parameters[$param] =& $var;
    return $this;
}

Что-то, что, кажется, работает в тесте

$a = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5, "f"=>6);
$v = array();
$t = array();
$i = 0;
foreach($a as $key => $value)
{
    $t[] = $key;
    $v[] = &$t[$i];
    $i++;
}

print_r($v);

результаты здесь: http://www.antiyes.com/test/hmm.php

как вы думаете, $ key & $ value в

$dbQuery->bind(':' . $key, $value);

передаются по ссылке?

ниже не работает


эта строка

$updatesKeyToValues[] = "`$key` = :$key";

Не могли бы вы изменить его на:

$updatesKeyToValues[] = "`" . $key ."` = " . ":" . $key;

и посмотрите, что получится?

0 голосов
/ 05 февраля 2010

Почему вы не используете построитель запросов?

Это всего лишь быстрое предположение, поскольку у меня не было достаточно времени, чтобы поиграть с самим создателем запросов.

$query = DB::update();
$query->set($updates);
// etc

Проверьте источник, и я уверен, что вы могли бы выяснить, как работает построитель запросов:)

...