التوثيق الروسي يحدث هنا
يمكنك تنزيله كأرشيف أو استنساخه من هذا الموقع أو تنزيله عبر الملحن (رابط إلى packagist.org):
composer require krugozor/database
krugozor/database
؟ krugozor/database
هي مكتبة فئة PHP >= 8.0 للعمل البسيط والمريح والسريع والآمن مع قاعدة بيانات MySql، وذلك باستخدام امتداد PHP mysqli.
العيوب الرئيسية لجميع المكتبات للعمل مع قاعدة بيانات MySQL في PHP هي:
int
و float
.krugozor/database
هي فئة للعمل مع MySqlmysqli
و mysqli_result
لإنشاء الأساليب التي تحتاج إلى العمل بها.krugozor/database
؟معظم الأغلفة لمختلف برامج تشغيل قواعد البيانات عبارة عن مجموعة من التعليمات البرمجية عديمة الفائدة ذات بنية مثيرة للاشمئزاز. مؤلفوها، الذين لا يفهمون الغرض العملي من أغلفةهم بأنفسهم، يحولونها إلى نوع من استعلامات المنشئين (منشئ SQL)، ومكتبات ActiveRecord وحلول ORM الأخرى.
مكتبة krugozor/database
ليست مما سبق. هذه مجرد أداة مناسبة للعمل مع SQL العادي ضمن إطار عمل MySQL DBMS - وليس أكثر!
العناصر النائبة - علامات مكتوبة خاصة مكتوبة في سلسلة استعلام SQL بدلاً من القيم الصريحة (معلمات الاستعلام) . ويتم تمرير القيم نفسها "لاحقًا"، كوسائط لاحقة للطريقة الرئيسية التي تنفذ استعلام SQL:
$ 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
إلى name
حقل النص not null
، ونوع منطقي false
إلى الحقل الرقمي flag
. ماذا يجب أن نفعل في هذه الحالة؟
false
لعمود tinyint
كقيمة 0
، و null
كسلسلة فارغة لعمود name
؟ونظرا للأسئلة المطروحة، تقرر تطبيق وضعين للتشغيل في هذه المكتبة.
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"
. يختلف هذا السلوك عن تحويل bool
إلى int
في PHP، حيث غالبًا ما يتم كتابة النوع المنطقي في MySql كرقم.numeric
إلى سلسلة وفقًا لقواعد التحويل الخاصة بـ PHPnull
إلى 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
يتم تجاهل قيمة أي وسيطات، ويتم استبدال العناصر النائبة بالسلسلة NULL
في استعلام SQL:
$ 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 " , " ! " )
بالنسبة لأولئك الذين اعتادوا على العمل مع شركة تنمية نفط عمان، سيبدو هذا غريبًا، لكن تنفيذ آلية تحدد ما إذا كان من الضروري تضمين قيمة العنصر النائب بين علامتي اقتباس في حالة واحدة أم لا، هي مهمة غير تافهة للغاية وتتطلب كتابة محلل كامل .
انظر في الملف ./console/tests.php