Русскоязычная документация находится тут
您可以将其作为存档下载,从该站点克隆,或通过 Composer 下载(链接到 packagist.org):
composer require krugozor/database
krugozor/database
? krugozor/database
是一个 PHP >= 8.0 类库,使用 PHP 扩展 mysqli 来简单、方便、快速、安全地使用 MySql 数据库。
在 PHP 中使用 mysql 数据库的所有库的主要缺点是:
int
和float
。krugozor/database
是一个用于使用 MySql 的类mysqli
和mysqli_result
机制来创建您需要使用的方法。krugozor/database
库?大多数各种数据库驱动程序的包装器都是一堆无用的代码,具有令人厌恶的架构。他们的作者并不理解包装器本身的实际用途,而是将它们转变为一种构建器查询(sql 构建器)、ActiveRecord 库和其他 ORM 解决方案。
krugozor/database
库不是以上任何一个。这只是一个在 MySQL DBMS 框架内使用常规 SQL 的便捷工具 - 仅此而已!
占位符—写入 SQL 查询字符串而不是显式值(查询参数)中的特殊类型标记。并且值本身“稍后”作为后续参数传递给执行 SQL 查询的 main 方法:
$ result = $ db -> query (
" SELECT * FROM `users` WHERE `name` = '?s' AND `age` = ?i " ,
" d'Artagnan " , 41
);
通过占位符系统传递的 SQL 查询参数由特殊的转义机制进行处理,具体取决于占位符的类型。那些。您不再需要将变量包装在转义函数类型mysqli_real_escape_string()
中或像以前一样将它们转换为数字类型:
<?php
// Previously, before each request to the DBMS, we did
// something like this (and many people still don't do it):
$ id = ( int ) $ _POST [ ' id ' ];
$ value = mysqli_real_escape_string ( $ mysql , $ _POST [ ' value ' ]);
$ result = mysqli_query ( $ mysql , " SELECT * FROM `t` WHERE `f1` = ' $ value ' AND `f2` = $ id " );
现在,快速编写查询变得很容易,最重要的是, krugozor/database
库完全防止了任何可能的 SQL 注入。
填料的类型及其用途如下所述。在熟悉填充器的类型之前,有必要了解库机制的工作原理。
PHP 是一种弱类型语言,在开发这个库时出现了意识形态上的困境。假设我们有一个具有以下结构的表:
` name ` varchar not null
` flag ` tinyint not null
并且库必须(出于某种原因,可能超出开发人员的控制)执行以下请求:
$ db -> query (
" INSERT INTO `t` SET `name` = '?s', `flag` = ?i " ,
null , false
);
在此示例中,尝试将null
值写入not null
文本字段name
,并将false
布尔类型写入flag
数字字段。在这种情况下我们该怎么办?
tinyint
列的false
值视为值0
,并将name
列的null
视为空字符串?针对提出的问题,决定本馆实行两种运营模式。
Mysql::MODE_STRICT
模式下,参数类型必须与占位符类型匹配。例如,尝试将值55.5
或'55.5'
作为整数占位符?i
参数传递将导致抛出异常: // set strict mode
$ db -> setTypeMode (Mysql:: MODE_STRICT );
// this expression will not be executed, an exception will be thrown:
// attempt to specify a value of type "integer" for placeholder of type "double" in query template "SELECT ?i"
$ db -> query ( ' SELECT ?i ' , 55.5 );
Mysql::MODE_TRANSFORM
模式是默认设置的,并且是一种“宽容”模式 - 如果占位符类型和参数类型不匹配,它不会抛出异常,而是尝试使用以下方法将参数转换为所需的占位符类型: PHP 语言本身。顺便说一句,作为该库的作者,我总是使用这种特定模式,我在实际工作中从未使用过严格模式( Mysql::MODE_STRICT
),但也许您会特别需要它。 Mysql::MODE_TRANSFORM
中允许以下转换:
int
类型(占位符?i
)string
和double
类型表示的浮点数bool
TRUE 转换为int(1)
,FALSE 转换为int(0)
null
转换为int(0)
double
类型(占位符?d
)string
和int
类型表示的整数bool
TRUE 变为float(1)
,FALSE 变为float(0)
null
转换为float(0)
string
类型(占位符?s
)bool
TRUE 转换为string(1) "1"
, FALSE 转换为string(1) "0"
。这种行为与 PHP 中将bool
转换为int
不同,在实践中,布尔类型在 MySql 中通常被写为数字。numeric
转换为字符串null
转换为string(0) ""
null
类型(占位符?n
)krugozor/database
库中提供了哪些类型的占位符? ?i
— 整数占位符 $ db -> query (
' SELECT * FROM `users` WHERE `id` = ?i ' , 123
);
模板转换后的SQL查询:
SELECT * FROM ` users ` WHERE ` id ` = 123
注意力!如果您对超出PHP_INT_MAX
限制的数字进行操作,则:
?s
(见下文)。重点是,超出PHP_INT_MAX
限制的数字,PHP 将解释为浮点数。库解析器将尝试将参数转换为int
类型,结果“结果将是未定义的,因为浮点数没有足够的精度来返回正确的结果。在这种情况下,既不会显示警告,也不会显示注释! ”——php.net。 ?d
— 浮点占位符 $ db -> query (
' SELECT * FROM `prices` WHERE `cost` IN (?d, ?d) ' ,
12.56 , ' 12.33 '
);
模板转换后的SQL查询:
SELECT * FROM ` prices ` WHERE ` cost ` IN ( 12 . 56 , 12 . 33 )
注意力!如果您使用库来处理double
数据类型,请设置适当的区域设置,以便整数和小数部分的分隔符在 PHP 级别和 DBMS 级别相同。
?s
— 字符串类型占位符使用mysqli::real_escape_string()
方法对参数值进行转义:
$ db -> query (
' SELECT "?s" ' ,
" You are all fools, and I am d'Artagnan! "
);
模板转换后的SQL查询:
SELECT " You are all fools, and I am d'Artagnan! "
?S
— SQL LIKE 运算符中替换的字符串类型占位符使用mysqli::real_escape_string()
方法+转义 LIKE 运算符中使用的特殊字符( %
和_
)对参数值进行转义:
$ db -> query ( ' SELECT "?S" ' , ' % _ ' );
模板转换后的SQL查询:
SELECT " % _ "
?n
— 占位符NULL
类型任何参数的值都将被忽略,占位符将替换为 SQL 查询中的字符串NULL
:
$ db -> query ( ' SELECT ?n ' , 123 );
模板转换后的SQL查询:
SELECT NULL
?A*
— 来自关联数组的关联集占位符,生成形式为key = value
的成对序列其中字符*
是占位符之一:
i
(整数占位符)d
(浮动占位符)s
(字符串类型占位符)转换和转义的规则与上述单个标量类型的规则相同。例子:
$ db -> query (
' INSERT INTO `test` SET ?Ai ' ,
[ ' first ' => ' 123 ' , ' second ' => 456 ]
);
模板转换后的SQL查询:
INSERT INTO ` test ` SET ` first ` = " 123 " , ` second ` = " 456 "
?a*
- 从简单(或关联)数组设置占位符,生成值序列其中*
是以下类型之一:
i
(整数占位符)d
(浮动占位符)s
(字符串类型占位符)转换和转义的规则与上述单个标量类型的规则相同。例子:
$ db -> query (
' SELECT * FROM `test` WHERE `id` IN (?ai) ' ,
[ 123 , 456 ]
);
模板转换后的SQL查询:
SELECT * FROM ` test ` WHERE ` id ` IN ( " 123 " , " 456 " )
?A[?n, ?s, ?i, ...]
— 关联集占位符,明确指示参数的类型和数量,生成key = value
对的序列例子:
$ db -> query (
' INSERT INTO `users` SET ?A[?i, "?s"] ' ,
[ ' age ' => 41 , ' name ' => " d'Artagnan " ]
);
模板转换后的SQL查询:
INSERT INTO ` users ` SET ` age ` = 41 , ` name ` = " d'Artagnan "
?a[?n, ?s, ?i, ...]
— 设置占位符,明确指示参数的类型和数量,生成值序列例子:
$ db -> query (
' SELECT * FROM `users` WHERE `name` IN (?a["?s", "?s"]) ' ,
[ ' Daniel O"Neill ' , " d'Artagnan " ]
);
模板转换后的SQL查询:
SELECT * FROM ` users ` WHERE ` name ` IN ( " Daniel O " Neill " , " d ' Artagnan")
?f
— 表或字段名称占位符此占位符适用于表或字段的名称作为参数在查询中传递的情况。字段和表名称用撇号括起来:
$ db -> query (
' SELECT ?f FROM ?f ' ,
' name ' ,
' database.table_name '
);
模板转换后的SQL查询:
SELECT ` name ` FROM ` database ` . ` table_name `
该库要求程序员遵循 SQL 语法。这意味着以下查询将不起作用:
$ db -> query (
' SELECT CONCAT("Hello, ", ?s, "!") ' ,
' world '
);
— 占位符?s
必须用单引号或双引号引起来:
$ db -> query (
' SELECT concat("Hello, ", "?s", "!") ' ,
' world '
);
模板转换后的SQL查询:
SELECT concat( " Hello, " , " world " , " ! " )
对于那些习惯使用 PDO 的人来说,这看起来很奇怪,但是实现一种机制来确定是否有必要在某种情况下将占位符值括在引号中是一项非常重要的任务,需要编写整个解析器。
请参阅文件 ./console/tests.php