Русскоязычная документация находится тут
Puede descargarlo como archivo, clonarlo desde este sitio o descargarlo a través de Composer (enlace a packagist.org):
composer require krugozor/database
krugozor/database
? krugozor/database
es una biblioteca de clases PHP >= 8.0 para trabajar de forma sencilla, cómoda, rápida y segura con la base de datos MySql, utilizando la extensión PHP mysqli.
Las principales desventajas de todas las bibliotecas para trabajar con la base de datos mysql en PHP son:
int
y float
.krugozor/database
es una clase para trabajar con MySqlmysqli
y mysqli_result
para crear los métodos con los que necesita trabajar.krugozor/database
?La mayoría de los contenedores para varios controladores de bases de datos son un montón de código inútil con una arquitectura desagradable. Sus autores, sin comprender el propósito práctico de sus envoltorios, los convierten en una especie de constructores de consultas (sql builder), bibliotecas ActiveRecord y otras soluciones ORM.
La biblioteca krugozor/database
no es ninguna de las anteriores. Esta es solo una herramienta conveniente para trabajar con SQL normal dentro del marco MySQL DBMS, ¡y nada más!
Marcadores de posición : marcadores de tipo especial que se escriben en la cadena de consulta SQL en lugar de valores explícitos (parámetros de consulta) . Y los valores en sí se pasan "más tarde", como argumentos posteriores al método principal que ejecuta una consulta SQL:
$ result = $ db -> query (
" SELECT * FROM `users` WHERE `name` = '?s' AND `age` = ?i " ,
" d'Artagnan " , 41
);
Los parámetros de consulta SQL pasados a través del sistema de marcadores de posición se procesan mediante mecanismos de escape especiales, según el tipo de marcadores de posición. Aquellos. ya no necesita envolver variables en funciones de escape tipo mysqli_real_escape_string()
o convertirlas a un tipo numérico como antes:
<?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 " );
Ahora se ha vuelto fácil escribir consultas, rápidamente y, lo más importante, la biblioteca krugozor/database
evita por completo cualquier posible inyección de SQL.
Los tipos de rellenos y sus finalidades se describen a continuación. Antes de familiarizarse con los tipos de rellenos, es necesario comprender cómo funciona el mecanismo de la biblioteca.
PHP es un lenguaje débilmente tipado y surgió un dilema ideológico al desarrollar esta biblioteca. Imaginemos que tenemos una tabla con la siguiente estructura:
` name ` varchar not null
` flag ` tinyint not null
y la biblioteca DEBE (por alguna razón, posiblemente fuera del control del desarrollador) ejecutar la siguiente solicitud:
$ db -> query (
" INSERT INTO `t` SET `name` = '?s', `flag` = ?i " ,
null , false
);
En este ejemplo, se intenta escribir un valor null
en el name
del campo de texto not null
y un tipo booleano false
en el campo numérico flag
. ¿Qué debemos hacer en esta situación?
false
de la columna tinyint
como el valor 0
y null
como una cadena vacía para la columna name
?En vista de las dudas planteadas, se decidió implementar dos modos de funcionamiento en esta biblioteca.
Mysql::MODE_STRICT
, el tipo de argumento debe coincidir con el tipo de marcador de posición . Por ejemplo, un intento de pasar el valor 55.5
o '55.5'
como argumento para un marcador de posición entero ?i
generará una excepción: // 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
está configurado de forma predeterminada y es un modo "tolerante": si el tipo de marcador de posición y el tipo de argumento no coinciden, no genera una excepción, pero intenta convertir el argumento al tipo de marcador de posición deseado usando el Lenguaje PHP en sí . Por cierto, yo, como autor de la biblioteca, siempre uso este modo en particular, nunca he usado el modo estricto ( Mysql::MODE_STRICT
) en el trabajo real, pero quizás lo necesites específicamente. Las siguientes transformaciones están permitidas en Mysql::MODE_TRANSFORM
:
int
(marcador de posición ?i
)string
como double
bool
TRUE se convierte a int(1)
, FALSE se convierte a int(0)
null
se convierte a int(0)
double
(marcador de posición ?d
)string
e int
.bool
TRUE se convierte en float(1)
, FALSE se convierte en float(0)
null
se convierte en float(0)
string
de tipo (marcador de posición ?s
)bool
TRUE se convierte en string(1) "1"
, FALSE se convierte en string(1) "0"
. Este comportamiento es diferente de convertir bool
a int
en PHP, ya que a menudo, en la práctica, el tipo booleano se escribe en MySql como un número.numeric
se convierte en una cadena de acuerdo con las reglas de conversión de PHPnull
se convierte en string(0) ""
null
(marcador de posición ?n
)krugozor/database
? ?i
- marcador de posición entero $ db -> query (
' SELECT * FROM `users` WHERE `id` = ?i ' , 123
);
Consulta SQL después de la conversión de plantilla:
SELECT * FROM ` users ` WHERE ` id ` = 123
¡ATENCIÓN! Si opera con números que están fuera de los límites de PHP_INT_MAX
, entonces:
?s
(ver más abajo). El punto es que los números más allá de los límites PHP_INT_MAX
, PHP los interpreta como números de punto flotante. El analizador de la biblioteca intentará convertir el parámetro al tipo int
, como resultado " el resultado no estará definido, ya que el flotante no tiene suficiente precisión para devolver el resultado correcto. En este caso, no se mostrará ni una advertencia ni un comentario". ! ”—php.net. ?d
— marcador de posición de punto flotante $ db -> query (
' SELECT * FROM `prices` WHERE `cost` IN (?d, ?d) ' ,
12.56 , ' 12.33 '
);
Consulta SQL después de la conversión de plantilla:
SELECT * FROM ` prices ` WHERE ` cost ` IN ( 12 . 56 , 12 . 33 )
¡ATENCIÓN! Si está utilizando una biblioteca para trabajar con el tipo de datos double
, configure la configuración regional adecuada para que el separador de las partes enteras y fraccionarias sea el mismo tanto en el nivel PHP como en el nivel DBMS.
?s
— marcador de posición de tipo cadena Los valores de los argumentos se escapan utilizando el método mysqli::real_escape_string()
:
$ db -> query (
' SELECT "?s" ' ,
" You are all fools, and I am d'Artagnan! "
);
Consulta SQL después de la conversión de plantilla:
SELECT " You are all fools, and I am d'Artagnan! "
?S
— marcador de posición de tipo cadena para sustitución en el operador LIKE de SQL Los valores de los argumentos se escapan usando el método mysqli::real_escape_string()
+ caracteres especiales de escape usados en el operador LIKE ( %
y _
):
$ db -> query ( ' SELECT "?S" ' , ' % _ ' );
Consulta SQL después de la conversión de plantilla:
SELECT " % _ "
?n
— tipo NULL
de marcador de posición El valor de cualquier argumento se ignora y los marcadores de posición se reemplazan con la cadena NULL
en la consulta SQL:
$ db -> query ( ' SELECT ?n ' , 123 );
Consulta SQL después de la conversión de plantilla:
SELECT NULL
?A*
— marcador de posición de conjunto asociativo a partir de una matriz asociativa, que genera una secuencia de pares de la forma key = value
donde el carácter *
es uno de los marcadores de posición:
i
(marcador de posición entero)d
(marcador de posición flotante)s
(marcador de posición de tipo cadena)Las reglas para la conversión y el escape son las mismas que para los tipos escalares individuales descritos anteriormente. Ejemplo:
$ db -> query (
' INSERT INTO `test` SET ?Ai ' ,
[ ' first ' => ' 123 ' , ' second ' => 456 ]
);
Consulta SQL después de la conversión de plantilla:
INSERT INTO ` test ` SET ` first ` = " 123 " , ` second ` = " 456 "
?a*
- establece un marcador de posición a partir de una matriz simple (o también asociativa), generando una secuencia de valores donde *
es uno de los tipos:
i
(marcador de posición entero)d
(marcador de posición flotante)s
(marcador de posición de tipo cadena)Las reglas para la conversión y el escape son las mismas que para los tipos escalares individuales descritos anteriormente. Ejemplo:
$ db -> query (
' SELECT * FROM `test` WHERE `id` IN (?ai) ' ,
[ 123 , 456 ]
);
Consulta SQL después de la conversión de plantilla:
SELECT * FROM ` test ` WHERE ` id ` IN ( " 123 " , " 456 " )
?A[?n, ?s, ?i, ...]
— marcador de posición de conjunto asociativo con una indicación explícita del tipo y número de argumentos, generando una secuencia de pares key = value
Ejemplo:
$ db -> query (
' INSERT INTO `users` SET ?A[?i, "?s"] ' ,
[ ' age ' => 41 , ' name ' => " d'Artagnan " ]
);
Consulta SQL después de la conversión de plantilla:
INSERT INTO ` users ` SET ` age ` = 41 , ` name ` = " d'Artagnan "
?a[?n, ?s, ?i, ...]
— establece un marcador de posición con una indicación explícita del tipo y número de argumentos, generando una secuencia de valoresEjemplo:
$ db -> query (
' SELECT * FROM `users` WHERE `name` IN (?a["?s", "?s"]) ' ,
[ ' Daniel O"Neill ' , " d'Artagnan " ]
);
Consulta SQL después de la conversión de plantilla:
SELECT * FROM ` users ` WHERE ` name ` IN ( " Daniel O " Neill " , " d ' Artagnan")
?f
— marcador de posición de nombre de tabla o campoEste marcador de posición está destinado a los casos en los que el nombre de una tabla o campo se pasa en la consulta como parámetro. Los nombres de campos y tablas están enmarcados con un apóstrofo:
$ db -> query (
' SELECT ?f FROM ?f ' ,
' name ' ,
' database.table_name '
);
Consulta SQL después de la conversión de plantilla:
SELECT ` name ` FROM ` database ` . ` table_name `
La biblioteca requiere que el programador siga la sintaxis SQL. Esto significa que la siguiente consulta no funcionará:
$ db -> query (
' SELECT CONCAT("Hello, ", ?s, "!") ' ,
' world '
);
— los marcadores de posición ?s
deben estar entre comillas simples o dobles:
$ db -> query (
' SELECT concat("Hello, ", "?s", "!") ' ,
' world '
);
Consulta SQL después de la conversión de plantilla:
SELECT concat( " Hello, " , " world " , " ! " )
Para aquellos que están acostumbrados a trabajar con PDO, esto les parecerá extraño, pero implementar un mecanismo que determine si es necesario encerrar el valor del marcador de posición entre comillas en un caso o no es una tarea nada trivial que requiere escribir un analizador completo. .
Ver en el archivo ./console/tests.php