بسم الله الرحمن الرحيم
شرح التعامل مع مكتبة PDO [الجزء الأول]
شرح التعامل مع مكتبة PDO [الجزء الثاني]
يتناول هذا الجزء ما يلي:
= إرشادات قبل البدء
= مقدمة
= التعليمات المجهزة Prepared Statements
= التعاملات Transactions
= خاتمة.
= فتح المجال طلب شرح آخر
= إرشادات قبل البدء:
* ملحوظة1: اذا لم يكن لديك اهتمام كبير بالمحافظة على عدم الضغط على السيرفر الذي يحتوي على برنامجك
أو تقليل وقت تكوين الصفحة، فاقفز إلى نقطتي الخاتمة وطلب شرح جديد.
* ملحوظة2: افضل طريقة لاستيعاب هذا الدرس هي قراءة قطة الشرح ثم قراءة الكود بالشرح ثم التعقيب ان وجد ثم التنفيذ بشكل عملي
* ملحوظة3: هذا الدرس مبني على فهم مسبق للدرسين الأول والثاني
* ملحوظة4: بما أننا في مرحلة التطوير للكود فاننا سنجعل مستوى الخطأ ERRMODE_EXCEPTION
لكن عند الانتهاء ننصح بارجاع الوضع الافتراضي ERRMODE_SILENT -> راجع الجزء 2 من الشرح.
= مقدمة:
هذا هو الجزء الثالث والأخير من شرع التعامل مع مكتبة PDO .. ويحتوي على أفضل ميزتين لهذه المكتبة
وهما حلين مثاليين لمن بتعامل مع قواعد البيانات بكثرة.
= التعليمات المجهزة Prepared Statements:
عندما نمرر استعلاما لقاعدة البيانات فانه يمر بعدة عمليات لكي ينفذ وهي التحليل->الترجمة->التخفيف.
و في حالة التعليمات المعقدة قد يطول وقت تنفيذ الثلاث عمليات ويزيد الضغط على موارد السيرفر أو وقت التنفيذ بشكل تلاحظه..
ومن هنا ظهرت الاستعلامات المجهزة .. حيث يتم حفظ نسخة من الاستعلام بعد مروره بالثلاث عمليات
ومن ثم ارجاعه او ارجاع جزء منه عند الحاجة لتنفيذه مرة أخرى.
وبما أن بعض قواعد البيانات لا تدعم هذه الميزة قامت مكتبة PDO بتوفير هذه الطريقة التي تتوافق مع كل قواعد البيانات التي تتعامل معها المكتبة لتشكل الحل الأمثل للتعامل مع الاستعلامات المجهزة مسبقا.
كل ما يلزمك هو أن تكتب الاستعلام مرة واحدة وترمز للقيمة التي ستتغير برمز معين لكي يتم استبداله بالقيمة المرادة مع كل طلب للاستعلام.
- الطريقة الأولى:
كود PHP:
try {
// الاتصال بقاعدة البيانات
$SQL = new PDO('mysql:host=localhost;dbname=test', 'root', '123456', array(PDO::ATTR_PERSISTENT => true));
$SQL->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
#>>>>>>>>>>>>>>>>------------------------------------------------>
// تجهيز الاستعلام و تحديد البارامترات المستخدمة
$stmt = $SQL->prepare('INSERT INTO article (name,body) VALUES (:name,:body)');
// نقول للمكتبة أن تربط قيمة البارامترات بقيم متغيرات نحددها
$stmt->bindParam(':name',$name);
$stmt->bindParam(':body',$body);
#>>>>>>>>>>>>>>>>------------------------------------------------>
// تحديد قيم المتغيرات
$name = 'article1';
$body = 'body1';
// تنفيذ الاستعلام.. حيث سيتم احلال قيم المتغيرات محل البارامترات المدخلة
$stmt->execute();
// اعطاء البارامترات قيم أخرى لاستعمالها مرة أخرى
$name = 'article2';
$body = 'body2';
// تنفيذ الاستعلام.. حيث سيتم احلال قيم المتغيرات محل البارامترات المدخلة .. ويمكنك التكرار عدد لا نهائي
$stmt->execute();
#>---------> أيضا يمكن الاستخدام هكذا <---------<#
// تقوم بعمل مصفوفة تحتوي على مفاتيح بأسماء البارامترات المدخلة و القيم المطلوب ادخالها
$arr = array('name'=>'article3', 'body'=>'body3');
// تمريرها لدالة التنفيذ
$stmt->execute($arr);
#>>>>>>>>>>>>>>>>------------------------------------------------>
// اغلاق الاتصال بالقاعدة
$SQL = null;
}catch(PDOException $e){
echo $e->getMessage();
}
- الطريقة الثانية باستخدام (؟) :
كود PHP:
try {
// الاتصال بقاعدة البيانات
$SQL = new PDO('mysql:host=localhost;dbname=test', 'root', '123456', array(PDO::ATTR_PERSISTENT => true));
$SQL->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
#>>>>>>>>>>>>>>>>------------------------------------------------>
// تجهيز الاستعلام و نلاحظ وضع علامات الاستفهام للدلالة على البارامترات
$stmt = $SQL->prepare('INSERT INTO article (name,body) VALUES (?,?)');
// لاحظ أننا استعملنا الارقام للدلالة على البارامترات
$stmt->bindParam(1,$name);
$stmt->bindParam(2,$body);
#>>>>>>>>>>>>>>>>------------------------------------------------>
// تحديد قيم المتغيرات
$name = 'article4';
$body = 'body4';
// تنفيذ الاستعلام.. حيث سيتم احلال قيم المتغيرات محل البارامترات المدخلة
$stmt->execute();
// اعطاء المتغيرات قيم أخرى لاستعمالها مرة أخرة
$name = 'article5';
$body = 'body5';
// تنفيذ الاستعلام.. حيث سيتم احلال قيم المتغيرات محل البارامترات المدخلة .. ويمكنك التكرار عدد لا نهائي
$stmt->execute();
#>---------> أيضا يمكن الاستخدام هكذا <---------<#
// تقوم بعمل مصفوفة تحتوي على القيم المطلوب ادخالها
$arr = array('article6', 'body6');
// تمريرها لدالة التنفيذ
$stmt->execute($arr);
/*>>>>>>>>>>>>>>>>------------------------------------------------>
أيضا وجب التنبيه على خطأ شائع عند استخدام هذه الطريقة كما سيتضح في هذا المثال:
$stmt = $SQL->prepare("SELECT * FROM article WHERE name LIKE '%?%' ");
$like = 'article';
$stmt->bindParam(1,$like);
$stmt->execute();
حيث أن علامة الاستفهام يجب أن تأتي مفردة ليست بداخل نص .. والحل الأمثل لذلك:*/
$stmt = $SQL->prepare("SELECT * FROM article WHERE name LIKE ? ");
$like = '%article%';
$stmt->bindParam(1,$like);
$stmt->execute();
while($row = $stmt>fetch()){
echo $row['name'],'<br />',$row['body'],'<br /><br />';
}
#>>>>>>>>>>>>>>>>------------------------------------------------>
// اغلاق الاتصال بالقاعدة
$SQL = null;
}catch(PDOException $e){
echo $e->getMessage();
}
* تجدر الاشارة إلى أنه لا يمكن استعمال النوعين معا داخل الاستعلام .. نوع واحد فقط
* يقال أن هذه الطريقة جيدة للوقاية من ال SQL injection حيث أن المكتبة تقوم بتنقية الكود ..
لكن هذا ليس في معظم الأحوال .. لذلك استعمل طرقك الخاصة في تنقية المدخلات ولا تعتمد المكتبة في التنقية.
= التعاملات Transactions:
هناك بعض قواعد البيانات التي تدعم التعاملات وبعضها لا يدعم .. لذلك يجب استعمالها مع القواعد التي تدعمها -بالطبع MySQL تدعمها
والآن ما هي قصة هذه التعاملات؟
بشكل مبسط.. كل استعلام نقوم بعمله يتطلب نوع من ال احتكاك بين PHP و قاعدة البيانات المطلوبة.
هذا بالطبع يترتب عليه استهلاك لموارد السيرفر وللوقت. و يؤثر بشكل كبير على قواعد البيانات الموجودة على شكلفي ملف..
مثل SQLite حيث أن هذا الملف يتم اغلاقه lock في كل مرة يتم فيها الاستعلام.
وهذا يعني وجود وقت ضائع وضغط غير مرغوب فيه.
ما يمكننا قوله بشأن التعاملات هو أن مع بداية التعامل ب beginTransaction يتم تجميع كل الاستعلامات المطلوبة
ثم تنفيذها دفعة واحدة عند اعطاء أمر commet أو أن يتم نسيانها وعدم تنفيذها عند استخدام أمر rollBack
أيضا هناك مزايا وطرق يمكن استعمالها لفرز هذه الاستعلامات والتعديل أو حذف ما سوف يتسبب في ارجاع الخطأ.لكن لم يتم ذكرها منعا للاطالة.
كود PHP:
try {
// الاتصال بقاعدة البيانات
$SQL = new PDO('mysql:host=localhost;dbname=test', 'root', '123456', array(PDO::ATTR_PERSISTENT => true));
$SQL->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
#>>>>>>>>>>>>>>>>------------------------------------------------>
// بداية التعامل
$SQL->beginTransaction();
// الآن نقوم بعمل مجموعة استعلامات بشكل عادي جدا
$SQL->exec('INSERT INTO article (name, body) VALUES (article7,body7)');
$SQL->exec('INSERT INTO article (name, body) VALUES (article8,body8)');
$SQL->exec('DELETE FROM article WHERE id = 3');
$SQL->exec('DELETE FROM article WHERE id = 5');
// ثم ننفذ العمليات
$SQL->commit();
#>---------> أو نتراجع عن التعامل ونلغي الاستعلامات المدخلة له <---------<#
$SQL->rollBack();
#>>>>>>>>>>>>>>>>------------------------------------------------>
// اغلاق الاتصال بالقاعدة
$SQL = null;
}catch(PDOException $e){
// نتراجع عن ما تم تخزينه من تعليمات
$SQL->rollBack();
echo $e->getMessage();
}
= خاتمة:
- تم بحمد الله شرح هذا الجزء. بالطبع ان أخطأت فمن نفسي ومن الشيطان وان أصبت فمن الله.
اذا كانت هناك أية أخطاء في الشرح أرجو ابرازها ليتم تعديلها.
- لي 3 أهداف من الشرح: توفير مستندات عربية لشرح أجزاء غير مغطاة حتى يكتب لنا الثواب باذن الله-
المساهمة في اثراء المكتبة العربية بهذه المستندات-واخيرا أعظم مقابل في نظري، وهو دعوة بظهر الغيب فلا تبخلوا علينا بها.
- جميع الحقوق محفوظة لكل مسلم.
= فتح المجال لاقتراح شرح آخر:
اذا كنت ترى جزءا من ال PHP غير واضح أو لا يوجد له تغطية ومستندات عربية، أو أنه اذا تم شرحه سيفيد الأهداف الثلاثة
فاطلب شرحه -حتى اذا كنت تتقنه فهناك من هو في حاجة له- وباذن الله نجتهد فيه.
أيضا اذا كانت لديك ملاحظات في أسلوب السرد أو اقتراحات فلا تتردد قي قولها.
ما سيأتي من شروح باذن الله سيكون عبارة عن موضوع مكتوب بالاضافة لملف مضغوط للامثلة و -اذا توفر الوقت- ملف فيديو للشرح العملي.
تم بحمد الله،،