php - 如果 MySQL 函数用于自定义类,则 MySQL 确定是否在字符串周围加上单引号

标签 php mysql regex class

我正在创建一个自定义类,以便更轻松地连接和使用 mysql。我创建了许多功能,除了一个部分外,其他功能都很好。我似乎无法弄清楚如何确定一个字符串是一个实际的字符串还是一个 mysql 函数以便在它周围加上引号。我将一个可以传递两个参数的函数放在一起,它将插入到数据库中。第一个参数是要插入的表,而第二个参数是列值对的数组。也许这个代码示例会帮助您了解更多。注意:我已经转义了所有字符串并删除了该代码以显示问题的简单性。

function insert($table,array $array){
    $table = "`".$table."`";
    $columns = "";
    $values = "";
    foreach($array as $key => $value){
        $columns = ($columns=="") ? "`".$key."`" : $columns.", `".$key."`";
        if($value===NULL || $value=="NULL"){
            $value = "NULL";
        } else {
            $value = "'".$value."'";
        }
        $values = ($values=="") ? "".$value."" : $values.", ".$value."";
    }
    $query = "INSERT INTO $table ($columns) VALUES ($values)";
    return $this->query($query);
}

这里是两个不同用途的例子以及各自的预期结果

$data = array(
  "first_name"=>"John",
  "last_name"=>"Doe",
  "entry_date"=>"2013-08-26"
);
$MyClass->insert("people",$data);

会执行

INSERT INTO `people` (`first_name`,`last_name`,`entry_date`) VALUES ('John','Doe','2013-08-26')

这是预期的但是以下用途:

$data = array(
  "first_name"=>"John",
  "last_name"=>"Doe",
  "entry_date"=>"NOW()"
);
$MyClass->insert("people",$data);

将执行为

INSERT INTO `people` (`first_name`,`last_name`,`entry_date`) VALUES ('John','Doe','NOW()')

这将不起作用,因为MySQL函数如果带引号将不会运行。我知道这可能是一个小的安全风险,因为如果不被捕获,它会允许用户使用功能。有没有更好的方法来做到这一点,或者应该不允许在这样的类插入函数中使用 MySQL 函数?如果有人将正则表达式放在一起以查找并允许 mysql 函数,那么这可能是一个解决方案。如果不存在这样的正则表达式,那么一种可能性是从头开始编写一个我不太擅长的......

编辑:

我将同时使用的另一个解决方案是在形成数组时使用 PHP 获取日期。如果可能的话,我还是想使用 MySQL 函数。这是我当前解决问题的代码,但不是我喜欢的方式:

$data = array(
  "first_name"=>"John",
  "last_name"=>"Doe",
  "entry_date"=>date('Y-m-d H:i:s'),
);
$MyClass->insert("people",$data);

最佳答案

几年前,我实现了一项功能来完成您所描述的 Zend Framework 1.0。

我通过区分普通字符串标量和包含字符串的对象 解决了这个问题。

$data = array(
  "first_name"=>"John",
  "last_name"=>"Doe",
  "entry_date"=>new Zend_Db_Expr("NOW()")
);
$MyClass->insert("people",$data);

这样我的框架就可以区分我打算处理的 PHP 字符串 作为 SQL 字符串(即带引号),而不是在对象中汇总的字符串。

if($value===NULL || $value=="NULL"){
    $value = "NULL";
} else if ($value instanceof Zend_Db_Expr) {
    $value = $value->__toString(); // no quotes
} else {
    $value = "'".$value."'";
}

PS:有些人可能会建议您使用查询参数,而不是像您这样做的那样连接转义变量。我同意这个建议,但它确实与你原来的问题没什么关系,所以我不会深入探讨。还有许多其他 StackOverflow 问题涉及使用查询参数。


回复你的评论:

您可以使用正则表达式来匹配 NOW() 和所有其他 MySQL 函数并特殊对待它们,但是您如何插入文字字符串“NOW()”(不是函数的结果那个名字)?

回答:你不能——就像你不能在你当前的代码中插入文字字符串“NULL”一样,因为你已经把这个词当作一个特例来对待。

您需要一些方法来区分 SQL 表达式 NOW() 和“NOW()”。仅仅因为您今天不需要将该字符串插入您的数据库并不意味着您将永远不需要该功能。请记住,您正在设计此 insert() 函数以针对当前或将来的任何 表进行一般使用。

你实际上是在设计一个框架。

关于php - 如果 MySQL 函数用于自定义类,则 MySQL 确定是否在字符串周围加上单引号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18452217/

相关文章:

python - 使用python将JSON导入mysql

mysql - 连接两个表并显示发票号码总金额的 SQL 查询

javascript - 如果字符串与 jquery 中的一行匹配,则禁用按钮

java - 在Java中使用RegEx提取括号之间的参数

php - 使用 Colorbox 和 JavaScript 函数

php - 每 24 小时重新发送一次电子邮件,持续 3 天

php - 访问包括应用程序文件夹中的文件夹。

php - 从带有数组的html表插入mysql

javax.naming.NameNotFoundException : Name [jdbc/spitterDS] is not bound in this Context. 无法找到 [jdbc]

regex - 合并行落在之间但不包括 sed 的重复模式