【问题标题】:My database query keeps setting all columns to the same value in MySQL我的数据库查询不断将所有列设置为 MySQL 中的相同值
【发布时间】:2010-02-05 00:37:07
【问题描述】:

这是我对 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 不接受数组。

最终更新

谢谢大家,我认为它是通过引用传递的。我通过将其设置为 $updates[$key]

来解决它

看起来我也可以使用param() 方法而不是绑定。 View source

【问题讨论】:

    标签: php database insert kohana


    【解决方案1】:

    绑定函数正在使用您的 $value 的引用

    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;
    

    看看会发生什么?

    【讨论】:

    【解决方案2】:

    我不知道您在这里使用的是什么数据访问层,但我猜是这样的:

    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:刚刚查看了您发布到 John 评论的链接中的 query.php。是的。叹。它通过引用获取参数。多么可怕。

    【讨论】:

    • 我认为你是对的 Bobince。我不想破解 Kohana 的系统文件,所以我将研究另一种方法。 +1
    • 我可以通过引用取消传递,还是我需要实现一个丑陋的 hack,例如为每个循环创建一个始终保持原样的临时变量?
    • 你能创建临时地图/数组吗?保持价值观?
    • 没试过,但 PHP 手册说你只能传递变量和“新”对象作为引用。多么不方便。是的,看起来 mysqli 做同样的事情。至少在 PDO 中,此错误功能是可选的(bindValue 也存在以按预期方式执行此操作)。
    • @alex 在该循环的末尾添加一个 unset($value) 应该可以做到。
    【解决方案3】:

    为什么不使用查询构建器?

    这只是一个快速的猜测,因为我自己没有足够的时间来使用查询生成器。

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

    查看源代码,我相信您可以弄清楚查询构建器的工作原理 :)

    【讨论】:

      猜你喜欢
      • 2013-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-23
      • 2013-08-27
      • 1970-01-01
      • 2017-02-12
      • 2018-10-09
      相关资源
      最近更新 更多