Русскоязычная документация находится тут
アーカイブとしてダウンロードすることも、このサイトからクローンを作成することも、composer (packagist.org へのリンク) 経由でダウンロードすることもできます。
composer require krugozor/database
krugozor/database
とは何ですか? krugozor/database
、PHP 拡張機能 mysqli を使用して、MySql データベースを簡単、便利、高速かつ安全に操作するための PHP 8.0 以降のクラス ライブラリです。
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
boolean 型をflag
数値フィールドに書き込もうとします。この状況では何をすべきでしょうか?
tinyint
列のfalse
値を値0
として扱い、 name
列のnull
空の文字列として扱うことはできますか?提起された質問を考慮して、このライブラリに 2 つの動作モードを実装することが決定されました。
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
はPHPの変換ルールに従って文字列に変換されます。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
型に変換しようとします。その結果、「 float には正しい結果を返すのに十分な精度がないため、結果は未定義になります。この場合、警告もコメントも表示されません」 ! 」 — 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
形式のペアのシーケンスを生成します。ここで、文字*
はプレースホルダーの 1 つです。
i
(整数のプレースホルダー)d
(浮動小数点プレースホルダー)s
(文字列型のプレースホルダー)変換とエスケープの規則は、上で説明した単一のスカラー型の規則と同じです。例:
$ db -> query (
' INSERT INTO `test` SET ?Ai ' ,
[ ' first ' => ' 123 ' , ' second ' => 456 ]
);
テンプレート変換後の SQL クエリ:
INSERT INTO ` test ` SET ` first ` = " 123 " , ` second ` = " 456 "
?a*
- 単純な (または連想的な) 配列からプレースホルダーを設定し、一連の値を生成しますここで、 *
次のタイプの 1 つです。
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 を参照してください。