درس پنجم- صفحه بندی و مرتب سازی رکوردها
مقدمه
از
درس ابتدایی دوره مقدماتی تا به اینجا ما درباره نکات بسیاری از پیاچپی و
پایگاه دادهها صحبت کردهایم. حال که دانش کافی در مورد این مباحث داریم
به سراغ مفاهیم بروز و پیشرفتهتر که در ساخت سیستمها از آنها استفاده
میشوند، میرویم. بدلیل اهمیت آنچه در قبل خواندهایم و اینکه از آنها در
دروس پیش رو استفاده خواهیم کرد اجازه بدهید که این درس را با شرحی خلاصه
وار به اندوختههایمان بپردازیم تا با یک مرور سریع آمادگی بیشتری در جذب
دادههای تازه پیدا کنیم. در ادامه به تکنیک مهم دیگری در ساخت یک سیستم
پویا میپردازیم.
یادآوری
وارد کردن فایل
برای واردکردن فایل در فایل دیگری از موارد زیر استفاده میشود.
- include('نام و نشانی فایل')
- include_once()
- require()
- require_once()
توابع
isset( $_POST['submit'] ) // اطمینان از ارسال دادهها توسط دکمه ارسال
empty($_POST['name']) // اطمینان از پربودن کادر فرم
$dbc = mysqli_connect ( hostname , username , password , db_name ); // اتصال به پایگاه
mysqli_connect_error( ) // برگرداندن متنی به عنوان اشکال در اتصال به پایگاه
mysqli_set_charset($dbc, 'utf8'); // تنظیم نوع رمزگذاری کاراکترها
$e = mysqli_real_escape_string($dbc, trim($_POST['email'])) ; // از بین بردن فاصلهها و کاراکترهای اضافه
$q = "SELECT * FROM users ORDER BY register_date ASC"; // پرسوجو
$r = @mysqli_query ($dbc, $q); // اجرای پرسوجو
$num = mysqli_num_rows($r); // شمارش تعداد دریافتیها
$row = mysqli_fetch_array($r, MYSQLI_ASSOC) //به داخل آرایه با کلید کلمهای دریافتها
$row = mysqli_fetch_array($r, MYSQLI_NUM); // به داخل آرایه با کلید شمارهای دریافتها
mysqli_free_result ($r); // آزادسازی منابع
mysqli_close($dbc); // بستن ارتباط با پایگاه
صفحه بندی
حتما قبلا با مراجعه به تارنماهای بسیاری با این قسمت روبرو شدید. مثلا در
موتور جستجوی گوگل در هنگام نمایش یافتهها اگر به قسمت پایین صفحه دقت
کنید، صفحه بندی را در قالب نمایش دادهها در صفحههای بیشماری مشاهده
خواهید کرد.
برای انجام این مهم ما از پوشهای که در دوره مقدماتی با هم ساختیم استفاده میکنیم. لطفا یک رونوشت از پوشه درس ۱۵ «ویرایش دادهها» گرفته و با نام تازه Pagination ثبت کنید. کار صفحه بندی را میخواهیم در برگه «کاربران» انجام دهیم، بطوریکه این برگه کاربران ثبت نام شده را در صفحههای متعددی با توجه به تعداد آنها و تعدادی که میخواهیم در یک صفحه دیده شود، نمایش دهد.
برای پیاده سازی صفحه بندی در برگه کاربران این برگه را باز نویسی میکنیم. یعنی کدهای آن را پاک کرده و از نو کدهای جدید را وارد میکنیم.
برگه کاربران view.php
کدهای قبلی را پاک کرده و این کدها را وارد کنید:
<?php
$page_title = 'صفحه بندی فهرست کاربران';
include('includes/header.php');
echo '<h1> کاربران </h1>';
require_once ('db_connection.php'); // ارتباط با پایگاه
// شماره تعداد رکوردها که میخواهیم در هر صفحه نمایان شود
$display = 2 ;
// بررسی ارسال عدد تعداد صفحه
if(isset($_GET['p']) && is_numeric($_GET['p'])){
$pages = $_GET['p']; }
else {
// گرفتن تعداد رکوردها از پایگاه
$query = "SELECT COUNT(ID) FROM users";
$run = mysqli_query($dbc, $query);
$rows = mysqli_fetch_array($run, MYSQLI_NUM);
$records = $rows[0];
// محاسبه تعداد صفحهها
if($records > $display){ // اگر تعداد رکوردها بیشتر از شماره انتخاب برای نمایش بود
$pages = ceil($records / $display); } // تعداد رکونها کن و به عدد صحیح بالاتر گرد کن
else {
$pages = 1 ; // اگر نه تعداد یک باشد
}
}// پایان انتخاب عدد تعداد صفحهها
// انتخاب محل شروع نتیجه پرسوجو در صفحه نمایش از پایگاه
if(isset($_GET['s']) && is_numeric($_GET['s'])){ // اگر نقطه شروع نمایش مشخص است
$start = $_GET['s']; } // نقطه شروع
else {
$start = 0; // (نقطه شروع از صفر باشد(منظور نقطه شروع پرسوجو از پایگاه است
}
$q = "SELECT * FROM users ORDER BY register_date ASC LIMIT $start, $display";
$r = mysqli_query($dbc,$q) or die("خطا: ".mysqli_error($dbc));
$records = mysqli_num_rows($r);
if ($records > 0) { // اگر دریافتی وجود داشت
// چاپ تعداد کاربرها
echo "<p> در این ردیف $records کاربر وجود دارد </p> ";
echo '<div id="view">';
// سربرگ جدول
echo '<div id="table-header">
<div class="table-header"> نام </div>
<div class="table-header"> نام خانوادگی </div>
<div class="table-header"> نام کاربری </div>
<div class="table-header" style="width:19.8%;"> رایانامه </div>
<div class="table-header"> تاریخ ثبت نام </div>
<div class="table-header"> پاک کردن </div>
<div class="table-header"> ویرایش</div>
</div>';
// دریافت و چاپ همه رکوردها
echo '<div id="table-record">';
while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {
echo '<div class="table-record">' . $row['first_name'] . '</div>' ;
echo '<div class="table-record">' . $row['last_name'] . '</div>' ;
echo '<div class="table-record">' . $row['username'] . '</div>' ;
echo '<div class="table-record" style="width:19.8%;">' . $row['email'] . '</div>' ;
echo '<div class="table-record">' . $row['register_date'] . '</div>' ;
echo '<div class="table-record">' . '<a href="delete.php?id=' . $row['ID']. '"> پاک کردن </a>' . '</div>' ;
echo '<div class="table-record">' . '<a href="edit.php?id=' . $row['ID']. '"> ویرایش </a>' . '</div>' ;
}
echo '</div>'; // پایان رکوردها
echo '</div>'; // پایان جدول
mysqli_free_result ($r); // آزادسازی منابع
mysqli_close($dbc); // بستن ارتباط با پایگاه
if($pages > 1){
echo '<div id="pagination">';
$current_page = ($start / $display) + 1 ;
if($current_page != $pages){
echo '<a href="view.php?s=' . ($start + $display) . '&p=' . $pages . '">بعدی </a>';
}
for($i = $pages; $i > 0 ; $i--){
if($i != $current_page){
echo '<a href="view.php?s=' . (($display *($i - 1))) . '&p=' . $pages . '">' . ' ' . convert($i) . ' ' . '</a>';
}
else{
echo '<span class="choosen">' . convert($i) . '</span>' . ' ';
}
} // for
if($current_page != 1 ){
echo '<a href = "view.php?s=' . ($start - $display) . '&p=' . $pages . '"> قبلی </a>'; }
echo '</div>';
}// if($pages > 1){
} else { // اگر رکوردی نبود
echo '<p class="error"> در حال حاضر کاربری وجود ندارد </p>'; }
include ('includes/footer.html');
?>
شرح کدها
ابتدا باید بدانیم که چند کاربران میخواهیم در هر برگه نمایش داده شوند.
این کار را با یک متغییر که نگهدارنده تعداد کاربران یک برگه خواهد بود
انجام میدهیم:
// شماره تعداد رکوردها که میخواهیم در هر صفحه نمایان شود
$display = 2 ;
غیر از تعداد کاربران هر صفحه دو چیز خیلی مهم دیگر که باید بدانیم، تعداد کل صفحهها و نقطه شروع نمایش دادهها با توجه به ترتیب آنها در پایگاه دادهها است. مسلما ما تعداد صفحهها را نمی دانیم و باید آن را بر اساس تعداد دادهها (تعداد کل کاربران) محاسبه کنیم. در مورد نقطه شروع نمایش باید گفت که، مثلا فرض کنید که میخواهید در هر صفحه دو کاربر نمایش دهید و تعداد کاربران شما جمعا ۱۰ است. حال در هر صفحه دو کاربر که میشود ۱۰ صفحه، اما برای اینکه هر صفحه دو کاربر داشته باشد و صفحه بعد ادامه صفحه قبل باشد باید نقطه آغاز نمایش کاربران و تعداد نمایش را مشخص کنیم. این کار را با یکی از ویژگیهای پایگاه دادهها یعنی LIMIT انجام میدهیم.
// بررسی ارسال عدد تعداد صفحه
if(isset($_GET['p']) && is_numeric($_GET['p'])){
$pages = $_GET['p']; }
این قسمت بررسی میکند که آیا تعداد صفحهها مشخص شده یا نه. در زمانی که شما برای نخستین بار وارد این صفحه شده و میخواهید بین کاربران جستجو کنید، مسلما این عدد مشخص نیست. اما زمانی که از قسمت صفحه بندی استفاده کردید، با نخستین انتخاب این عدد فرستاده خواهد شد. پس این قسمت فقط در زمان نخستین اقدام کاربرد دارد.
else { // گرفتن تعداد رکوردها از پایگاه
$query = "SELECT COUNT(ID) FROM users";
$run = mysqli_query($dbc, $query);
$rows = mysqli_fetch_array($run, MYSQLI_NUM);
$records = $rows[0];
// محاسبه تعداد صفحهها
if($records > $display){ // اگر تعداد رکوردها بیشتر از شماره انتخاب برای نمایش بود
$pages = ceil($records / $display); } // تعداد رکودها کن و به عدد صحیح بالاتر گرد کن
else {
$pages = 1 ; // اگر نه تعداد یک باشد }
در صورتی که برای نخستین بار وارد برگه کاربران شویم ما تصویر زیر را مشاهده میکنیم.
همانطور که میبینید عدد یک به رنگ قرمز نشان میدهد که شما در برگه ابتدایی هستید. در این زمان هیچ مقداری برای تعداد صفحهها فرستاده نشده پس ما باید این عدد را مشخص کنیم. قسمت else این کار را برای ما انجام میدهد.
ابتدا با یک پرسوجو تعداد کل دادهها را با شمارش ستون ID و با استفاده از تابع COUNT() بدست میآوریم. بدین ترتیب ما تعداد کاربران را داریم که البته درون متغییری به نام $records قرار میدهیم.
اگر تعداد رکوردها کمتر از تعداد کاربرانی که ما در متغییر $display مشخص کردیم باشد، پس ما فقط یک برگه لازم داریم تا آنها را نمایش دهیم. اما اگر تعداد کاربران بیشتر از تعداد مشخص شده باشد ما باید تعداد برگهها را حساب کنیم.
$pages = ceil($records / $display);
تابع ceil()تعداد رکوردها را بر تعداد تعیین شده تقسیم و نتیجه را به عدد بزرگتر صحیح گرد میکند. مثلا اگر ۵ رکود باشد این عدد را بر ۲ که قبلا در $display گذاشتیم میکند. نتیجه میشود ۲،۵ اما این عدد به ۳ که عدد صحیح بزرگتر است تبدیل میگردد. حال ما ۳ صفحه برای نمایش ۵ کاربر داریم. دو برگه ابتدایی ۲ و برگه سوم یک کاربر را نمایش میدهند.
// انتخاب محل شروع نتیجه پرسوجو در صفحه نمایش از پایگاه
if(isset($_GET['s']) && is_numeric($_GET['s'])){ // اگر نقطه شروع نمایش مشخص است
$start = $_GET['s']; } // نقطه شروع
else {
$start = 0; // (نقطه شروع از صفر باشد(منظور نقطه شروع پرسوجو از پایگاه است
}
این قسمت نقطه شروع نمایش رکوردهای گرفته شده از پایگاه را میگیرد که اگر یادتان باشد گفتیم که رکوردها در پایگاه با عدد صفر شروع میشوند. خب، اگر در برگه ابتدایی باشید به قسمت elseرفته و نقطه شروع صفر میشود، تعداد هم که ۲، پس میشود رکورد ۰ و ۱ که دو رکورد هستند. قسمت بعدی که گرفتن دادهها از پایگاه است که بارها تکرار شده، پس به سراغ نمایش اعداد صفحه بندی میرویم. تنها نکته استفاده از LIMIT $start, $display است که کار پرسوجو را بصورت نقطه شروع و تعداد رکوردها برای هر برگه انجام میدهد.
if($pages > 1){
echo '<div id="pagination">';
$current_page = ($start / $display) + 1 ; // تعیین عدد برگه فعال فعلی
if($current_page != $pages){ // عدم برابری برگه فعلی با تعداد برگهها. در صورت برابری یعنی نمایش صفحه آخر
echo '<a href="view.php?s=' . ($start + $display) . '&p=' . $pages . '">بعدی </a>'; }
for($i = $pages; $i > 0 ; $i--){
if($i != $current_page){
echo '<a href="view.php?s=' . (($display *($i - 1))) . '&p=' . $pages . '">' . ' ' . convert($i) . ' ' . '</a>'; }
else{ echo '<span class="choosen">' . convert($i) . '</span>' . ' '; }
} // for
if($current_page != 1 ){
echo '<a href = "view.php?s=' . ($start - $display) . '&p=' . $pages . '"> قبلی </a>'; }
echo '</div>'; }
این قسمت زمانی اجرا میشود که تعداد صفحههای محاسبه شده در قسمت ابتدایی بیشتر از یک باشد. این بخش خود به سه قسمت تقسیم میشود. قسمت ابتدایی برای نمایش پیوند «بعدی»، قسمت دوم برای نمایش پیوند عدد برگهها و قسمت آخر برای نمایش پیوند «قبلی». ابتدا عدد برگه فعلی بدست میآید. اگر عدد برگه فعلی با عدد کل برگهها برابر شود این یعنی که در برگه آخر قرار داریم و نیازی به نمایش کلمه «بعدی» نیست زیرا رکورد بعدی وجود ندارد. اگر دقت کنید میبینید که در داخل پیوندها دو مقدار را از طریق مرورگر به برگه بعدی میفرستیم. تعداد صفحه و نقطه شروع، که در قسمت بالا در ابتدای شرح کد به قسمتی اشاره کردیم که این دو مقدار را دریافت میکنند.
محاسبه نقطه شروع نمایش رکوردها در سه پیوند انجام گرفته تا هر پیوند نقطه شروع مناسب را به همراه تعداد صفحهها به برگه بعدی که انتخاب میشود بفرستد. پیوند «بعدی» و «قبلی» که کاملا مشخص است که مجموع و منهای دو متغییر$start و $displayهستند. در میان این دو پیوند با کمک یک حلقه اعداد صفحهها را نمایش دادهایم که کاملا مشخص هستند. تنها نکته که باید به آن توجه کنید استفاده از تابع convert() است، این تابع را نوشته و در این قسمت آوردهایم تا اعداد را به اعداد پارسی تبدیل کنیم. در درس توابع دوره مقدماتی این تابع را شرح دادیم.
تغییرات در دیگر برگهها
ساخت فایل توابع
یک فایل دیگر با نام functions.php در کنار سربرگ و پایین برگ در پوشه includes برای گذاشتن توابع مورد نیازمان میسازیم و کد زیر را در داخل آن قرار میدهیم.
<?php
/* انگلیسی به پارسی */
function convert($string) {
$persian = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹');
$num = range(0, 9);
return str_replace($num, $persian, $string);
}
// ends ---
?>
فایل header.html
فایل توابع را در این قسمت وارد کنید، به صورت زیر:
همانطور که میبینید در قسمت بالای برگه سربرگ این کد گذاشته شده است.
فایل شیوهدهی css
برای نمایش بهتر پیوندهای صفحه بندی کد زیر را به فایل شیوه خود اضافه کنید:
/* pagination */
#pagination{border:0px solid #aaa; text-align:center; height:30px; margin:10px auto auto; padding:5px;}
#pagination a { text-decoration:none; font-size:20px;}
span.choosen{color:red; font-size:22px;}
مرتب سازی رکوردها
دوباره به سراغ برگه کاربران رفته و یک ویژگی جدید به آن اضافه میکنیم.
این ویژگی را اضافه کردن قابلیت مرتب سازی بر اساس نام و نام خانوادگی و
... مینامیم. این کار بسیار ساده است. فقط باید کمی تغییرات در فایل view.php بدهیم.
تغییرات فایل کاربران view.php
میخواهیم توانایی مرتب سازی را به این برگه اضافه کنیم. بعد از انجام تغییرات باید برگه مانند تصویر زیر داشته باشیم:
همانطور که میبینید قسمتهای نام، نام خانوادگی ، نام کاربری و تاریخ ثبت نام بصورت پیوند هستند. این به این دلیل است که با فشردن هر کدام مقدار مرتب کننده را باید به برگه بفرستیم. البته به دلیل تفاوتها در زبان پارسی و زبان پایگاه دادهها این شیوه برای کلمات پارسی خوب کار نمیکند و باید با انجام کارهای دیگری این نقض را برطرف کرد که در درسهای آینده بدان خواهیم پرداخت.
در بالای صفحه درست زیر قسمت بررسی برای نقطه شروع کدهای زیر را قرار دهید. توجه کنید که برای مشخص شدن محل ما کدهای بررسی نقطه آغاز جستوجو را هم در بالای آن گذاشتهایم:
// انتخاب محل شروع نتیجه پرسوجو در صفحه نمایش از پایگاه
if(isset($_GET['s']) && is_numeric($_GET['s'])){ // اگر نقطه شروع نمایش مشخص است
$start = $_GET['s']; } // نقطه شروع
else {
$start = 0; // (نقطه شروع از صفر باشد(منظور نقطه شروع پرسوجو از پایگاه است
} تا این قسمت در فایل موجود است باید از اینجا به بعد را اضافه کنید.
// قابلیت مرتب سازی بر اساس نام، نام خانوادگی و ...
$sort = (isset($_GET['sort'])) ? $_GET['sort'] : 'rd' ;
switch ($sort){
case 'ln':
$order_by = 'last_name ASC' ;
break ;
case 'fn':
$order_by = 'first_name ASC';
break;
case 'un':
$order_by = 'username ASC';
break;
case 'rd':
$order_by = 'register_date ASC';
break;
default:
$order_by = 'register_date ASC';
$sort = 'rd';
break;
}
این کار فقط با یک تغییر کوچک در نحوه پرسوجو انجام میشود که به این ترتیب ما برای هر برگه گزینه مرتب سازی را هم میفرستیم و از آن در داخل پرسوجو استفاده میکنیم:
$q = "SELECT * FROM users ORDER BY $order_by LIMIT $start, $display";
همانطور که میبینید در مقابل ORDER BY از متغییر $order_by استفاده کردیم که با توجه به مقدار آن دادهها را برایمان مرتب میکند.
نقطه دیگر که باید تغییر کند تبدیل کردن تیتر جدول نمایش کاربران به پیوندی برای مرتب سازی است:
<div class="table-header"><a href="view.php?sort=fn"> نام </a></div>
<div class="table-header"><a href="view.php?sort=ln"> نام خانوادگی </a></div>
<div class="table-header"><a href="view.php?sort=un"> نام کاربری </a></div>
<div class="table-header" style="width:19.8%;"> رایانامه </div>
<div class="table-header"><a href="view.php?sort=rd"> تاریخ ثبت نام </a></div>
با کمی دقت متوجه میشوید که تیتر جدول به پیوندهایی برای ارسال مقدار متغییر sort تبدیل شدهاند. این مقدار توسط برگه گرفته میشود و با استفاده از یک شرطی switch مقدار متغییر $order_byکه در پرسوجو برای مرتب سازی استفاده میشود را تغییر میدهد. البته این مقدار باید توسط پیوندهای قسمت صفحه بندی هم فرستاده شوند تا در صورت مرتب سازی و استفاده از صفحه بندی تداخل بوجود نیاید.
if($current_page != $pages){
echo '<a href="view.php?s=' . ($start + $display) . '&p=' . $pages . '&sort=' . $sort . '">بعدی </a>'; }
for($i = $pages; $i > 0 ; $i--){
if($i != $current_page){
echo '<a href="view.php?s=' . (($display *($i - 1))) . '&p=' . $pages . '&sort=' . $sort . '">' . ' ' . convert($i) . ' ' . '</a>';
}else{ echo '<span class="choosen">' . convert($i) . '</span>' . ' '; }
} // for
if($current_page != 1 ){
echo '<a href = "view.php?s=' . ($start - $display) . '&p=' . $pages . '&sort=' . $sort . '"> قبلی </a>'; }
بعد از انجام تغییرات اگر به نشانی مرورگر دقت کنید متوجه میشوید که با هر انتخابی مقادیری به نشانی فرستاده میشود.
در درس آینده به چند تکنیک دیگر در پیاچپی مانند فرستادن رایانامه و ارسال فایل اشاره خواهیم کرد.
اگر قبلا در بیان ثبت نام کرده اید لطفا ابتدا وارد شوید، در غیر این صورت می توانید ثبت نام کنید.