مقدمة
تقسيم الصفحات هو مفهوم مهم في بناء التطبيقات القائمة على البيانات. عند سحب السجلات من قاعدة البيانات، قد يتم جلب عدد كبير من السجلات. على سبيل المثال، عند تشغيل استعلام للمستخدمين النشطين أو المستخدمين الذين ينتمون إلى موقع معين، يمكن إرجاع عدد كبير من المستخدمين بالمئات أو حتى الآلاف. إن عرض هذا العدد الهائل من السجلات على صفحة ويب واحدة ليس حلاً سهلاً للمستخدم لأنه قد يربك المستخدم بالإضافة إلى إفساد سلاسة تجربة المستخدم.
وبالتالي، فإن الخيار الأفضل هو تقييد عدد السجلات. هذا هو مفهوم تقسيم الصفحات. وبعبارة أخرى، نقوم بتقسيم عدد السجلات إلى صفحات ثم نعرض الصفحة. يمكن أن تحتوي الصفحة الواحدة على عشرة أو حتى خمسة عشر أو أي كمية أخرى من السجلات الممكنة التي يمكن عرضها في الواجهة الأمامية.
بينما يمكن لتقسيم الصفحات تحسين تجربة المستخدم الإجمالية للتطبيق، فإنه يمكن أيضًا أن يجعل التطبيق أسرع نظرًا لأنه يمكننا استرداد عدد أقل من السجلات. وبالتالي، يتم نقل بيانات أقل عبر الشبكة بين العميل والخادم، مما يقلل من وقت الاستجابة.
في هذا البرنامج التعليمي، سنقوم ببناء PHP برمجية تتصل بقاعدة البيانات وتنفذ تقسيم الصفحات باستخدام قاعدة بيانات MySQL وعبارة LIMIT الخاصة بها.
المتطلبات الأساسية
لمتابعة هذا البرنامج التعليمي، ستحتاج إلى:
-
أحدث إصدار من Ubuntu، قيد التشغيل. اتبع برنامج تعليمي حول كيفية إعداد خادم Ubuntu الخاص بك إذا كنت بحاجة إلى مساعدة.
-
ستحتاج أيضًا إلى تثبيت PHP و MySQL. لإعداد PHP و MySQL، لدينا برنامج تعليمي: إعداد LAMP Stack – Linux Apache MySQL PHP.
الخطوة 1 — إعداد مستخدم قاعدة بيانات وقاعدة بيانات تجريبية
في هذا البرنامج التعليمي، سنقوم بإنشاء اتصال قاعدة البيانات مع قاعدة بيانات MySQL وجلب السجلات. سيتم عرض هذه السجلات على صفحة HTML باستخدام عنصر الجدول. لإنشاء الاتصال وعرض السجلات، سنستخدم سكربت PHP. بمجرد أن نكون جاهزين للاتصال بقاعدة البيانات، سنختبر تطبيقنا مع تقسيم الصفحات وبدونه. سيسمح لنا الاختبار بهذه الطريقة بفهم كيفية عمل تقسيم الصفحات عمليًا.
لاتصال بقاعدة بيانات MySQL، سنحتاج إلى قاعدة بيانات MySQL تجريبية ومعلومات مصادقة المستخدم للاتصال بقاعدة بيانات MySQL. في هذه الخطوة، ستنشئ مستخدمًا غير جذر (non-root) لقاعدة بيانات MySQL الخاصة بك، وقاعدة بيانات تجريبية، وجدولاً لاختبار سكربت PHP.
أولاً، قم بتسجيل الدخول إلى الخادم الخاص بك. ثم قم بتسجيل الدخول إلى خادم MySQL باستخدام الأمر أدناه:
|
1 |
mysql> sudo mysql -u root -p |
سيُطلب منك إدخال كلمة مرور المستخدم root. أدخل كلمة المرور واضغط على Enter للمتابعة. بعد ذلك، قم بإنشاء قاعدة بيانات تجريبية تسمى test_db، والتي سنستخدمها في برنامجنا التعليمي. لإنشاء قاعدة بيانات جديدة، قم بتشغيل الأمر أدناه:
|
1 |
mysql> Create database test_db; |
سترى مخرجات من خادم MySQL تفيد بتأثر صف واحد. بعد ذلك، سنحتاج إلى إنشاء مستخدم جديد لقاعدة البيانات هذه. سنمنح هذا المستخدم جميع الصلاحيات. ومع ذلك، عند العمل مع تطبيقات عملية، تأكد من تقييد الصلاحيات. سنطلق على مستخدمنا اسم test_user. في الأمر أدناه، استبدل PASSWORD بكلمة مرور قوية:
|
1 |
mysql> GRANT ALL PRIVILEGES ON test_db.* TO 'test_user'@'localhost' IDENTIFIED BY 'PASSWORD'; |
بمجرد إنشاء المستخدم، قم بتحديث الصلاحيات (flush):
|
1 |
mysql> FLUSH PRIVILEGES; |
الآن بعد أن أصبح كل من test_user و test_db جاهزين، استخدم test_db لإنشاء الجداول. للانتقال إلى test_db، قم بتشغيل الأمر أدناه:
|
1 |
mysql> Use test_db; |
بمجرد أن نرى تغيير قاعدة البيانات في المخرجات، سنكون جاهزين لإنشاء جدولنا. سنقوم بإنشاء جدول جديد يسمى Products للاحتفاظ بالمنتجات. لأغراضنا، سنحتاج إلى عمودين فقط في هذا الجدول: product_id و product_name. سنقوم بتعيين product_id إلى AUTO_INCREMENT، بحيث يتم تزايده في كل مرة نضيف فيها منتجًا جديدًا. العمود الآخر المسمى product_name سيُستخدم لتخزين اسم المنتج. العمود product_name سيُستخدم لتمييز كل منتج بالاسم:
|
1 |
mysql> Create table products (product_id BIGINT PRIMARY KEY AUTO_INCREMENT, product_name VARCHAR(50) NOT NULL ) Engine = InnoDB; |
الآن سنقوم بإضافة بعض المنتجات إلى هذا الجدول الذي تم إنشاؤه حديثًا. لتنفيذ هذا، قم بتشغيل الأوامر أدناه:
|
1 2 3 4 5 6 7 8 9 10 |
mysql> Insert into products(product_name) values ('WIRELESS MOUSE'); mysql> Insert into products(product_name) values ('BLUETOOTH SPEAKER'); mysql> Insert into products(product_name) values ('GAMING KEYBOARD'); mysql> Insert into products(product_name) values ('320GB FAST SSD'); mysql> Insert into products(product_name) values ('17 INCHES TFT'); mysql> Insert into products(product_name) values ('SPECIAL HEADPHONES'); mysql> Insert into products(product_name) values ('HD GRAPHIC CARD'); mysql> Insert into products(product_name) values ('80MM THERMAL PRINTER'); mysql> Insert into products(product_name) values ('HDMI TO VGA CONVERTER'); mysql> Insert into products(product_name) values ('FINGERPRINT SCANNER'); |
للتحقق مما إذا كان قد تم إدخال هذه المنتجات في الجدول، قم بتشغيل الأمر أدناه:
|
1 |
mysql> select * from products; |
إذا رأيت المنتجات التي قمت بإدخالها أعلاه، فأنت جاهز تمامًا للمضي قدمًا. اخرج من قاعدة بيانات MySQL باستخدام الأمر أدناه:
|
1 |
mysql> quit; |
الآن بعد أن قمنا بإعداد قاعدة بيانات MySQL وأدخلنا بيانات الاختبار، نحن جاهزون لكتابة كود PHP للاتصال بقاعدة البيانات هذه وجلب السجلات.
الخطوة 2 – جلب السجلات وعرضها بدون تقسيم الصفحات
كما تمت مناقشته أعلاه، سنقوم أولاً بعرض السجلات بدون تقسيم الصفحات. سنقوم ببناء سكربت PHP يتصل بقاعدة بيانات MySQL ويجلب السجلات. سنتصل بـ test_db التي أنشأناها أعلاه باستخدام test_user وجلب السجلات.
جدول products الخاص بنا يحتوي حاليًا على عشرة سجلات فقط. قد لا يكون واضحًا للعديد من المستخدمين ما إذا كان تقسيم الصفحات مطلوبًا أم غير مطلوب. ومع ذلك، فإن اختبار التطبيق بدون تقسيم الصفحات سيوضح كيف يساعد ذلك في التجربة العامة للتطبيق. سنفهم أيضًا كيف يساعد تقسيم البيانات في إنشاء تجربة مستخدم أفضل وتقليل العبء على الخادم.
في خادم PHP الخاص بك، في المجلد الرئيسي للموقع (document root)، قم بتشغيل الأمر أدناه:
sudo nano /var/www/html/pagination_test.php
الآن في هذا الملف، أضف المحتوى أدناه. تأكد من استبدال PASSWORD بقيمة كلمة المرور الخاصة بـ test_user:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php try { $pdo = new PDO("mysql:host=localhost;dbname=test_db", "test_user", "PASSWORD"); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); $sql = "select * from products"; $stmt = $pdo->prepare($sql); $stmt -> execute(); echo "<table border='1' align='center'>"; while (($row = $stmt -> fetch(PDO::FETCH_ASSOC)) !== false) { echo "<tr>"; echo "<td>".$row['product_id']."</td>"; echo "<td>".$row['product_name']."</td>"; echo "</tr>"; } echo "</table>"; } catch(PDOException $e) { echo $e->getMessage(); } ?> |
احفظ الملف. قبل أن نمضي قدمًا، سنلخص ما قمنا به أعلاه:
-
أولاً، قمنا بالاتصال بقاعدة بيانات MySQL، ولهذا استخدمنا مكتبة PHP Data Object (PDO) . استخدمنا بيانات اعتماد مستخدم MySQL التي استخدمناها أعلاه للاتصال بقاعدة بيانات MySQL. تعد PDO مكتبة مفيدة للغاية تُستخدم للاتصال بقاعدة البيانات. فهي تجعل طبقة الوصول إلى البيانات سهلة البرمجة وتسمح بالاتصال بقواعد بيانات متنوعة دون الحاجة إلى إعادة هيكلة التطبيق بشكل كبير. تستخدم PDO البيانات المعدة مسبقًا مما يضمن عدم المساس بالأمان. وبالتالي، يتم تنفيذ الاستعلامات بشكل آمن.
-
بعد ذلك، استخدمنا PDO API لتنفيذ عبارة select * from products . تضمن $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false) أن تكون أنواع البيانات في PHP هي نفسها الموجودة في قاعدة البيانات. وبالتالي، يظهر product_id و product_name كعدد صحيح وسلسلة نصية على التوالي.
-
تقوم $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); بإخبار PDO بطرح استثناء في حالة حدوث خطأ. ومن خلال القيام بذلك، يمكننا بسهولة التقاط الاستثناء في كتلة try … catch ومعالجته حسب الحاجة.
الآن بعد أن أصبح البرنامج النصي جاهزًا، يتعين علينا تشغيله. للقيام بذلك، افتح متصفحك وقم بزيارة عنوان URL: /var/www/html/pagination_test.php. تأكد من إلحاق عنوان URL بعنوان IP الخاص بخادمك. إذا كنت تقوم بالتشغيل محليًا، فسيصبح عنوان URL الخاص بك http://localhost/var/www/html/pagination_test.php.
سترى المخرجات أدناه:

هنا، يتم إرجاع منتجاتنا وعرضها على الصفحة. الآن، تخيل لو كان لدينا مئات المنتجات. سيؤدي ذلك إلى حلقة تكرارية طويلة لجلب البيانات وعرضها على الصفحة. سيؤدي هذا إلى زيادة وقت تحميل الصفحة.
في القسم التالي، سنقوم بتعديل برنامج PHP النصي وتضمين MySQL LIMIT . سيؤدي هذا إلى حل مشكلة عرض عدد كبير من السجلات. سنقوم بإضافة روابط تقسيم الصفحات حتى يتمكن المستخدم من التنقل عبر الصفحات.
الخطوة 3 – إعداد تقسيم الصفحات باستخدام PHP
في هذه الخطوة، سنقوم بإعداد تقسيم الصفحات باستخدام PHP لعرض البيانات باستخدام جداول متعددة. ولملاءمة تقسيم الصفحات، سنقوم بتعديل البرنامج النصي الذي قمنا ببرمجته في الخطوة السابقة.
سنستخدم LIMIT الخاصة بقاعدة بيانات MySQL. قبل إضافة هذا إلى البرنامج النصي، دعنا نرى مثالاً على صيغة MySQL LIMIT :
|
1 |
mysql> Select [column1, column2, column n...] from [table name] LIMIT offset, records; |
في العبارة أعلاه، يمكننا أن نرى أن LIMIT تحتوي على offset و records كمعاملات. offset تحدد عدد السجلات التي يجب تخطيها و records تحدد الحد الأقصى لعدد السجلات التي سيتم عرضها لكل صفحة أو جلبها من قاعدة البيانات.
الآن بعد أن عرفنا كيف يعمل تقسيم الصفحات، دعنا نلقي نظرة على كيفية تنفيذه. سنقوم بعرض ثلاثة سجلات في الصفحة الواحدة. لذا، إذا كان لدينا عشرة سجلات في قاعدة البيانات الخاصة بنا، فسيكون لدينا أربع صفحات عن طريق تقسيم العدد الإجمالي للسجلات على عدد السجلات في الصفحة الواحدة. وبما أن النتيجة قد لا تكون عدداً صحيحاً، فسنستخدم دالة PHP Ceil لتقريب النتيجة إلى أقرب عدد صحيح للحصول على عدد صحيح. فيما يلي مقتطف برمجى بسيط لتوضيح دالة Ceil :
|
1 |
$total_pages=ceil($total_records/$per_page); |
الآن سنقوم بإضافة الكود الخاص بتقسيم الصفحات. لتمكين تقسيم الصفحات وإضافة روابط التنقل، افتح ملف /var/www/html/pagination_test.php باستخدام الأمر أدناه:
|
1 |
$ sudo nano /var/www/html/pagination_test.php |
بعد ذلك، استبدل محتويات هذا الملف بالكود أدناه:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<?php try { $pdo = new PDO("mysql:host=localhost;dbname=test_db", "test_user", "PASSWORD"); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); /* بدء معلومات تقسيم الصفحات */ $page = 1; if (isset($_GET['page'])) { $page = filter_var($_GET['page'], FILTER_SANITIZE_NUMBER_INT); } $per_page = 3; $sqlcount = "select count(*) as total_records from products"; $stmt = $pdo->prepare($sqlcount); $stmt->execute(); $row = $stmt->fetch(); $total_records = $row['total_records']; $total_pages = ceil($total_records / $per_page); $offset = ($page-1) * $per_page; /* نهاية معلومات تقسيم الصفحات */ $sql = "select * from products limit :offset, :per_page"; $stmt = $pdo->prepare($sql); $stmt->execute(['offset'=>$offset, 'per_page'=>$per_page]); echo "<table border='1' align='center'>"; while ( ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) !== false) { echo "<tr>"; echo "<td>".$row['product_id']."</td>"; echo "<td>".$row['product_name']."</td>"; echo "</tr>"; } echo "</table>"; /* بدء التنقل */ echo "<table border='1' align='center'>"; echo "<tr>"; if ($page-1 >= 1) { echo "<td><a href=".$_SERVER['PHP_SELF']."?page=".($page - 1).">السابق</a></td>"; } if ($page+1 <= $total_pages) { echo "<td><a href=".$_SERVER['PHP_SELF']."?page=".($page + 1).">التالي</a></td>"; } echo "</tr>"; echo "</table>"; /* نهاية التنقل */ } catch(PDOException $e) { echo $e->getMessage(); } ?> |
إليك ملخص لهذا الكود:
-
يتعين علينا الاحتفاظ بالمعلومات المتعلقة بالصفحة التي نتواجد عليها حاليًا. ولهذا الغرض نستخدم $page المتغير. ويُسخدم $page المتغير لاستخراج الصفحة التي نتواجد عليها حاليًا باستخدام $_GET[‘page’] المتغير.
-
بعد ذلك، نحتاج إلى تحديد عدد العناصر التي سنعرضها في الصفحة. ولهذا الغرض نستخدم $per_page متغير. هنا نقوم بعرض ثلاثة منتجات فقط في كل صفحة.
-
كما تمت مناقشته أعلاه، نحتاج إلى الحصول على العدد الإجمالي للسجلات الموجودة في قاعدة البيانات. هذا مطلوب حتى نتمكن من تحديد العدد الإجمالي للصفحات. الـ $total_records متغير يحتفظ بهذه المعلومات.
-
أخيرًا، نحتاج إلى معرفة عدد السجلات التي يجب تخطيها. على سبيل المثال، إذا كنا في الصفحة الثانية، فنحن بحاجة إلى تخطي السجلات الثلاثة الأولى في قاعدة البيانات. نحن نستخدم الـ $offset متغير للاحتفاظ بهذه المعلومات. لقد قمنا بحساب هذه المعلومات عند كل تحميل للصفحة باستخدام الصيغة $offset=($page-1)*$per_page. إذا كنت بحاجة إلى عرض أي عدد آخر من العناصر، يمكنك تحديد القيمة في الـ $per_page متغير.
-
لعرض أزرار التنقل، نستخدم الكود أدناه:
|
1 2 3 4 5 6 7 8 9 10 |
. . . if( $page-1>=1) { echo "<td><a href=".$_SERVER['PHP_SELF']."?page=".($page-1).">السابق</a></td>"; } if( $page+1<=$total_pages) { echo "<td><a href=".$_SERVER['PHP_SELF']."?page=".($page+1).">التالي</a></td>"; } . . . |
المنطق هو أن الـ $page يُستخدم للاحتفاظ بالصفحة الحالية. إذا أردنا عرض الخيار السابق على الصفحة، فسيقوم السكربت بطرح واحد من قيمة الـ $page متغير. إذا كانت النتيجة أكبر من أو تساوي واحدًا، فسيتم عرض الخيار السابق على الصفحة.
وبالمثل، لعرض الخيار التالي، نضيف واحدًا إلى الـ $page متغير. هنا نتأكد من أن نتيجة الإضافة يجب ألا تتجاوز العدد الإجمالي للصفحات في الـ $total_pages متغير.
بعد ذلك، حان الوقت للتحقق من الصفحة. افتح المتصفح وانتقل إلى الصفحة باستخدام عنوان URL الذي استخدمته من قبل:
|
1 |
http://your_server_ip/pagination_test.php |
سترى المخرجات كما يلي:



هنا قمت أخيرًا بتنفيذ تقسيم الصفحات باستخدام عبارة LIMIT الخاصة بـ MySQL في سكربت PHP. من خلال تنفيذ تقسيم الصفحات في تطبيقك، سيكون لديك طريقة أفضل للتنقل عبر سجلات متعددة.
الخاتمة
في هذا البرنامج التعليمي، تعرفنا على كيفية تنفيذ تقسيم الصفحات باستخدام PHP و MySQL على Ubuntu. باستخدام هذه الخطوات، يمكنك بناء تطبيقات يمكنها عرض عدد كبير من السجلات بشكل مناسب، مقسمة عبر الصفحات للتعامل معها بفعالية.
بالإضافة إلى ذلك، لدينا المزيد من البرامج التعليمية المفيدة حول PHP و MySQL باستخدام Ubuntu:
- تثبيت وتأمين phpMyAdmin على Ubuntu 18.04
- كيفية إعادة تعيين كلمة مرور جذر (Root) لـ MariaDB أو MySQL
- برنامج CloudSigma التعليمي: كيفية إعداد MySQL على خادم وأساسيات MySQL
حوسبة سعيدة!
التعليقات
لا توجد تعليقات بعد. كن أول من يعلق.