iandreyev/safemysqlplus

处理MySQL查询的真正安全、方便的方法。

1.1.1 2023-02-12 19:30 UTC

This package is auto-updated.

Last update: 2024-09-15 15:23:11 UTC


README

SafeMySQL是一个用于安全、方便处理MySQL查询的PHP类。

  • 之所以安全,是因为每个动态查询部分都通过占位符进入查询
  • 之所以方便,是因为它使得应用程序代码简短且具有意义,没有无用的重复,使它更加“额外”地遵循DRY原则

这个类有三个主要特点

  • 与标准库不同,它使用类型提示占位符,用于可能放入查询的一切
  • 与标准库不同,它不需要重复绑定、检索等,因为它提供了一系列辅助方法,可以直接从查询中获得所需的结果
  • 与标准库不同,它可以解析占位符,不仅限于整个查询,还可以是任意的查询部分,这得益于不可或缺的parse()方法,使得复杂查询像常规查询一样简单、安全。

然而,它非常容易使用。你只需要学习一些东西

  1. 你必须始终通过占位符传递任何动态数据到查询中
  2. 每个占位符必须标记数据类型。目前有六种类型
  • ?s ("字符串") - 字符串(也包括DATEFLOATDECIMAL
  • ?i ("整数") - 如其名所示
  • ?n ("名称") - 标识符(表和字段名称)
  • ?a ("数组") - 复杂占位符,用于IN()运算符(替换为'a','b','c'格式的字符串,不带括号)
  • ?u ("更新") - 复杂占位符,用于SET运算符(替换为'字段'='值','字段'='值'格式的字符串)
  • ?p ("解析") - 特殊类型占位符,用于插入已解析的语句,无需任何处理,以避免重复解析。
  1. 为了从查询中直接获取数据,有一系列辅助方法用于最常用的
  • query($query,$param1,$param2, ...) - 返回mysqli资源。
  • getOne($query,$param1,$param2, ...) - 返回标量值
  • getRow($query,$param1,$param2, ...) - 返回一维数组,一行
  • getCol($query,$param1,$param2, ...) - 返回一维数组,一列
  • getAll($query,$param1,$param2, ...) - 返回二维数组,行数组
  • getInd($key,$query,$par1,$par2, ...) - 返回索引二维数组,行数组
  • getIndCol($key,$query,$par1,$par2, ...) - 返回一维数组,索引列,由键=>值对组成
  1. 对于任何复杂情况,始终使用parse()方法。然后插入

其余的就像平常一样 - 只需创建一个带有占位符的常规SQL(),然后获取结果

  • $name = $db->getOne('SELECT name FROM table WHERE id = ?i',$_GET['id']);
  • $data = $db->getInd('id','SELECT * FROM ?n WHERE id IN (?a)','table', array(1,2));
  • $data = $db->getAll("SELECT * FROM ?n WHERE mod=?s LIMIT ?i",$table,$mod,$limit);

这个类的主要特点是带有类型提示的占位符。这比仅仅在预处理语句中使用序号占位符又前进了一大步。简单地说,查询的动态部分不仅限于标量数据!在现实生活中,我们不得不添加标识符、用于IN运算符的数组,以及用于INSERTUPDATE查询的数组。所以——我们需要很多不同类型的数据格式化。因此,我们需要一种方法来告诉驱动器如何格式化这些特定的数据。传统的预处理语句通常使用繁琐且重复的bind_*函数。但有一种更加优雅且实用的方法——就是在占位符本身设置类型。这不是什么新东西——众所周知的printf()函数就是使用相同的机制。所以,我犹豫着是否要借鉴这样一个绝妙的想法。

要实现这样的功能,毫无疑问,必须拥有自己的查询解析器。没问题,这不是什么大问题。但好处是无穷无尽的。看看Stack Overflow上所有的问题,开发者们都在徒劳地尝试绑定字段名。看吧——有了标识符占位符,添加字段值就像一样简单。

$field = $_POST['field'];
$value = $_POST['value'];
$sql   = "SELECT * FROM table WHERE ?n LIKE ?s";
$data  = $db->query($sql,$field,"%$value%");

没有什么是更简单的了!

当然,我们会为常见类型提供占位符——字符串和数字。但既然我们已经开始发明新的占位符——让我们再发明一些!

在创建预处理查询时,另一个麻烦是用于IN运算符的数组。每个人都试图用自己的方法来做,但类型提示占位符使得这就像添加一个字符串一样简单。

$array = array(1,2,3);
$data  = $db->query("SELECT * FROM table WHERE id IN (?a)",$array);

对于像INSERTUPDATE这样的繁琐查询也是如此。

当然,我们还提供了一套辅助函数,可以将类型提示占位符转换为真正的精彩,使得几乎每个数据库调用都像一行或两行代码那样简单,用于所有常见的实际任务。