【问题标题】:pdo database abstractionpdo 数据库抽象
【发布时间】:2009-11-13 19:16:31
【问题描述】:

谁能帮我看看这个设置出了什么问题

我像这样在下面的函数中构建@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 );

谢谢,理查德

【问题讨论】:

    标签: php syntax pdo


    【解决方案1】:

    如果您使用 PDO,为什么不使用 bindParam()bindValue() 方法 demonstated here

    【讨论】:

    • 谢谢,我会调查一下,如果这样可以解决问题
    • 您还可以拥有多个包含字段/值的数组吗?一个用于更新,一个用于条件。因为如果我看到这个-:$stmt->execute($values);那么只有一个与参数绑定的数组被执行?
    【解决方案2】:

    不要使用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 子句中的参数,我建议您在指定参数占位符名称时区分字段。这样,如果您在两个子句中引用相同的字段(一个用于搜索旧值,另一个用于设置新值),就不会发生冲突。

    也许":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);
    

    【讨论】:

    • 谢谢,这很有帮助,我已经在一个函数中构建了 4 个循环,因为我对此不太熟悉。不过我得仔细看看。
    • 您可以使用array_map()join() 而不是所有这些循环来收紧您的代码。
    • 谢谢,你哪里更快,我没用过那些功能,所以我也去看看
    • 如果你能展示一个小例子,如何使用 array_map 来提高效率,那就太好了。您的意思是创建一个匿名回调函数来执行 stmt->bindparam?
    • Ì 上面的代码有问题,它不会给出好的结果如果我做 ':set'.$field 并将它与 ':set'.$k 绑定,那么我会出错字段中的值。我通过删除集合对其进行了测试,但随后我还需要将数组添加到 execute()。所以,我不得不重新考虑一下。
    猜你喜欢
    • 2011-03-17
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    • 2015-12-14
    • 1970-01-01
    • 2015-06-09
    • 2014-01-07
    • 2012-11-22
    相关资源
    最近更新 更多