() translation by (you can also view the original English article)
یادم میاد که سالهای پیش، زمانی که برای اولین بار با پیاچپی وMySQL شروع به کد نویسی کردم، چقدر هیجان شده شده بودم وقتی که برای اولین بار اطلاعات را از پایگاه داده گرفتم و در مرورگر نمایش دادم.
برای کسی که دانش کمی در مورد پایگاهداده و برنامه نویسی داشت، دیدن آن سطرهای جدول روی صفحه نمایش بر اساس کدی که نوشتم (حالا قبول که مثال رو از یک کتاب کپی کرده بودم، موهای خودتان رو نکَنید) حس پیروزی بهم دست میداد. شاید در آن زمان، از تمام اتفاقات سحرآمیزی پشت قضیه رخ میداد آگاهی نداشتم، اما آن اولین موفقیت، منجر به کار کردن روی پروژهای بزگتر و بهتری شد.
اگر چه سطح دانش من از پایگاه داده ممکن است به همان اندازه قبل نباشد،
اما از همان اولین برخورد من با "سلام دنیا" در پیاچپی و مایاسکیوال، من جذب
این قدرت شدم که هرچیزی را ساده و به طوری که به راحتی قابل استفاده باشد بسازم.
به عنوان یک توسعهدهنده، یکی از مشکلاتی که همیشه با آن روبهرو هستم، این است که حجم زیادی از داده را بتوانم به نحوی نمایش دهم که راحتر قابل درک باشد. چه لیست مشتریهای یک شرکت بزرگ باشد یا کاتالوگ فایلهای mp3 شخصی، نشستن و نگاه کردن به ردیفها روی ردیفها روی ردیفها داده کاری دلسرد
و خسته کننده ست. یه توسعه دهنده خوب برای این قضیه چکار میتواند انجام دهد؟ صفحهبندی کند!
۱. صفحهبندی کردن
صفحهبندی یعنی پروسه دریافت نتایج و پخش کردن آنها
در صفحات متعدد تا نمایش دادهها راحتتر شود.



من همان اوایل فهمیدم که اگر ۵ هزار ردیف از اطلاعات دارم که باید نمایش دهم، این قضیه نه تنها
باعث ایجاد سردرد برای کسی که میخواد دادهها را بخواند میشود،
بلکه برای اکثر مرورگرها باعث میشود زمان زیادی (بیش از ۵ ثانیه) طول بکشد تا دادهها نمایش داده شوند.
برای حل این مشکل، من دستورات SQL مختلفی را برای بیرون کشیدن تکههایی از دادهها مینوشتم، و اگر
حال داشتم، شاید چندتا دکمه "بعدی" و "قبلی"
هم اضافه میکردم، و از این قطعه کد در پروژههای مشابه استفاده میکردم و تغییراتی را روی آن انجام میدادم
تا با دادهها آن پروژه سازگار شود. این کار سریع بود. و همانطور که یک توسعهدهندهی خوب میداد، تنبلی باعث ایجاد خلاقیت میشود
یا چیزی شبیه آن. بنابراین، یه روز با خودم نشستم و تصمیم گرفتم که یک کلاس ساده
و انعطافپذیر پیاچپی بسازم که به صورت اتوماتیک کاراهای کوچک را
برایم انجام دهد.
یک چیزی در مورد خودم و کلاسهای پیاچپی بگم. من یکی از خفنهای شیگرایی نیستم. در حقیقت،
من خیلی به ندرت از این چیزا استفاده میکنم. اما وقتی که چندتا مثال و آموزش در مورد برنامه نویسی شیگرا خوندم و چندتا
مثال ساده سعی و خطا انجام دادم، تصمیم گرفتم بهش یک شانس بدم و میدانید چی شد؟
خیلی خوب برای صفحهبندی جواب میدهد. کدی که اینجا استفاده شده برای پیاچپی ۴ نوشته شده اما
با پیاچپی ۵ هم کار خواهد کرد.
۲. پایگاه داده
عاشق MySQL هستم. قصد توهین به دیگر سیستمهای پایگاه داده را ندارم، اما برای
من، تمام چیزی که نیاز دارم MySQL است. و یکی از ویژگیهای خوب MySQL این است که به شما چندتا
نمونه پایگاه داده به آدرس زیر به صورت رایگان میدهد تا بتوانید با آنها تمرین کنید.
.http://dev.mysql.com/doc/#sampledb
برای مثال، من از پایگاهداده جهان (حدوداٌ ۹۰ کلیوبایت زیپ شدهست) استفاده میکنم که بیش از
۴هزار رکورد جهت تمرین کردن دارد. اما نکته خوب اسکریپت پیاچپی که قرار هست با هم بنویسیم این هست
که برای هر پایگاهدادهای قابل استفاده است. حالا فکرمیکنم، همه موافق هستیم که اگر تصمیم بگیریم
که نتایج را صفحه بندی نکنیم در نهایت با یه سری نتایج طولانی و بدقواره
شبیه این مواجه میشویم:

(برای سایز اصلی کلیک کنید، عکس به طورمسخرهای خیلی دراز است ~ ۳۳۸ کیلوبایت)
خیل خب، بیایید دادههایمان را به لقمههای کوچکتر قابل هضم تقسیم کنیم چیزی شبیه این:



قشنگ شد، نه؟ وقتی که از کلاس صفحهبندی در کد خودتان استفاده کنید
میتواند به راحتی و سریع حجم زیادی از دادهها را تبدیل به چندین صفحه کنید
آن هم تنها فقط با چند خط کد. واقعا!
۳. صفحه بند
این مثال از دو اسکریپت ساخته خواهد شد. کلاس قابل استفاده مجدد صفحهبند و فایل ایندکس که آیتمهای جدول و کنترلها را نمایش میدهد.
Paginator.class.php
کلاس صفحهبند تنها دو متد و یک سازنده (constructor) خواهد داشت. ما این کلاس را به صورت قدم به قدم میسازیم و همانطور که پیش میرویم هر گام را توضیح میدهیم.
1 |
<?php
|
2 |
|
3 |
class Paginator { |
4 |
|
5 |
private $_conn; |
6 |
private $_limit; |
7 |
private $_page; |
8 |
private $_query; |
9 |
private $_total; |
10 |
|
11 |
}
|
در اینجا فقط متغییرهای عضو کلاس صفحهبند تعریف شدهاند، از آنجایی که این کلاس، یک کلاس کمک کنندهست و هدف آن صفحهبندی کردن است، این کلاس نیاز به یک کانکشن معتبر به سرور MySQL دارد و همچنین یک کوئری از پیش تعریف شده که ما پارامترهای ضروری را با آن ادغام میکنیم تا نتایج را صفحهبندی کنیم. با متد سازنده شروع میکنیم.
1 |
<?php
|
2 |
|
3 |
public function __construct( $conn, $query ) { |
4 |
|
5 |
$this->_conn = $conn; |
6 |
$this->_query = $query; |
7 |
|
8 |
$rs= $this->_conn->query( $this->_query ); |
9 |
$this->_total = $rs->num_rows; |
10 |
|
11 |
}
|
ساده بود، نه؟ این متد، برای شی مورد نظر متغییرهای ارتباط پایگاه داده و کوئری را مقداردهی میکند، پس از آن تعداد کل ردیفهایی که توسط آن کوئری بدون اعمال هیچگونه پارامتر محدود کنندهای به دست میآید را محاسبه میکند. این تعداد کل ردیفها جهت ساخت لینکها برای صفحهبند ضروری است.
دقت کنید برای سادگی ، در اینجا ما هیچگونه بررسی خطا یا صحتسنجی برای پارامترهای داده شده انجام نمیدهیم، اما در برنامههای واقعی نهایی این بررسی ها نیاز است که انجام شوند.
دریافت نتایج
حال بیایید آن متدی را بسازیم که دادهها را صفحهبندی میکند و نتایج را برمیگرداند.
1 |
<?php
|
2 |
public function getData( $limit = 10, $page = 1 ) { |
3 |
|
4 |
$this->_limit = $limit; |
5 |
$this->_page = $page; |
6 |
|
7 |
if ( $this->_limit == 'all' ) { |
8 |
$query = $this->_query; |
9 |
} else { |
10 |
$query = $this->_query . " LIMIT " . ( ( $this->_page - 1 ) * $this->_limit ) . ", $this->_limit"; |
11 |
}
|
12 |
$rs = $this->_conn->query( $query ); |
13 |
|
14 |
while ( $row = $rs->fetch_assoc() ) { |
15 |
$results[] = $row; |
16 |
}
|
17 |
|
18 |
$result = new stdClass(); |
19 |
$result->page = $this->_page; |
20 |
$result->limit = $this->_limit; |
21 |
$result->total = $this->_total; |
22 |
$result->data = $results; |
23 |
|
24 |
return $result; |
25 |
}
|
بیایید این قطعه کد را گام به گام برسی کنیم، در ابتدا پارامترهای حد (limit) و صفحه (page) را تنظیم میکنیم، که در اینجا این مقادیر به صورت پیشفرض ۱۰ و ۱ تنظیم شدند. سپس بررسی میکنیم که آیا کاربر تعداد مشخصی از ردیفها را میخواد یا همهی آنها را میخواهد، بر اساس این بررسی و پارامتر صفحه، ما پارامتر LIMIT
را تنظیم میکنیم، "۱-" در پارامتر صفحه در واقع نشان دهندی این است که شماره صفحات از ۱ شروع میشود نه از صفر.
سپس کوئری را اعمال و نتایج را دریافت میکنیم، درنهایت ما یک شی جدید نتایج میسازیم که شامل پارامترهای limit و page و total از کوئری اعمال شده و داده برای هر کدام از ردیفهای دریافت شده میباشد.
نمایش لینکهای صفحهبندی
حالا، متدی را که از آن برای دریافت لینکهای صفحهبندی استفاده میشود مینویسیم.
1 |
<?php
|
2 |
public function createLinks( $links, $list_class ) { |
3 |
if ( $this->_limit == 'all' ) { |
4 |
return ''; |
5 |
}
|
6 |
|
7 |
$last = ceil( $this->_total / $this->_limit ); |
8 |
|
9 |
$start = ( ( $this->_page - $links ) > 0 ) ? $this->_page - $links : 1; |
10 |
$end = ( ( $this->_page + $links ) < $last ) ? $this->_page + $links : $last; |
11 |
|
12 |
$html = '<ul class="' . $list_class . '">'; |
13 |
|
14 |
$class = ( $this->_page == 1 ) ? "disabled" : ""; |
15 |
$html .= '<li class="' . $class . '"><a href="?limit=' . $this->_limit . '&page=' . ( $this->_page - 1 ) . '">«</a></li>'; |
16 |
|
17 |
if ( $start > 1 ) { |
18 |
$html .= '<li><a href="?limit=' . $this->_limit . '&page=1">1</a></li>'; |
19 |
$html .= '<li class="disabled"><span>...</span></li>'; |
20 |
}
|
21 |
|
22 |
for ( $i = $start ; $i <= $end; $i++ ) { |
23 |
$class = ( $this->_page == $i ) ? "active" : ""; |
24 |
$html .= '<li class="' . $class . '"><a href="?limit=' . $this->_limit . '&page=' . $i . '">' . $i . '</a></li>'; |
25 |
}
|
26 |
|
27 |
if ( $end < $last ) { |
28 |
$html .= '<li class="disabled"><span>...</span></li>'; |
29 |
$html .= '<li><a href="?limit=' . $this->_limit . '&page=' . $last . '">' . $last . '</a></li>'; |
30 |
}
|
31 |
|
32 |
$class = ( $this->_page == $last ) ? "disabled" : ""; |
33 |
$html .= '<li class="' . $class . '"><a href="?limit=' . $this->_limit . '&page=' . ( $this->_page + 1 ) . '">»</a></li>'; |
34 |
|
35 |
$html .= '</ul>'; |
36 |
|
37 |
return $html; |
38 |
}
|
این یک متد طولانی هست، چیزی حدود ۳۴ خط کد، خب ببینیم در این متد چه چیزهایی اتفاق میافتد.
- اول بررسی میکنیم که آیا کاربر تعداد مشخصی لینک نیاز دارد یا همهی لینکها را نیاز دارد، اگر مورد دوم اتفاق افتاده باشد یعنی همه لینکها مورد نیاز باشند در این صورت تنها یک رشته خالی را برمیگردانیم زیرا صفحهبندی نیاز نیست.
- پس آن، آخرین صفحه را بر اساس تعداد کل ردیفهای موجود و تعداد آیتمهایی که در هر صفحه نیاز است محاسبه میکنیم.
- سپس از پارامتر links که مشخص میکند چه تعداد لینک بعد و قبل از صفحه کنونی باید نمایش داده شود استفاده میکنیم و لینکهای شروع و پایان را میسازیم.
- و حالا از تگ ایجاد لیست استفاده می کنیم و مقدار کلاس آن برابر با پارامتر لیست کلاس قرار میدهیم و لینک صفحه قبلی را اضافه میکنیم، توجه کنید که برای لینک صفحه قبل، چک میکنیم که آیا صفحهی کنونی صفحه اول هست یا خیر، اگر صفحهی اول باشد خاصیت disabled لینک را فعال میکنیم.
- در اینجا درصوتی که لینک شروع، اولین لینک نباشد ما لینکی به صفحهی اول و نماد سه نقطه را نمایش میدهیم .
- سپس لینکهای بعد و قبل صفحه کنونی را بر اساس پارامتراهای شروع و پایان که پیشتر محاسبه شد نشان میدهیم. درهر دور حلقه، لینک صفحه نمایش میدهید و خاصیت کلاس لینک را بر اساس صفحه کنونی تنظیم میکنیم.
- پس از این، یک نماد سه نقطه دیگر و لینک به صفحه آخر در صورتی که لینک پایان آخرین لینک نباشد نشان میدهیم.
- در نهایت، لینک "صفحه بعدی" را نشان میدهیم و وضعت disabled را وقتی که کاربر در صفحه آخر هست را فعال میکنیم. لیست را میبندیم و رشته HTML تولید شده را برمیگردانیم.
این تمام چیزی بود که به Paginator.class مربوط بود. البته میشد setters و getters را برای متغییر های database connection, limit, page, query و total تنظیم کرد اما برای سادگی، ما این کلاس را به همین صورت نگه میداریم.
۴. index.php
حالا فایلی که مسئول استفاده از کلاس صفحهبند هست و نمایش دادههاست را میسازیم. اول بذارید کد HTML پایه را نشانتان دهم.
1 |
<!DOCTYPE html>
|
2 |
<head>
|
3 |
<title>PHP Pagination</title> |
4 |
<link rel="stylesheet" href="css/bootstrap.min.css"> |
5 |
</head>
|
6 |
<body>
|
7 |
<div class="container"> |
8 |
<div class="col-md-10 col-md-offset-1"> |
9 |
<h1>PHP Pagination</h1> |
10 |
<table class="table table-striped table-condensed table-bordered table-rounded"> |
11 |
<thead>
|
12 |
<tr>
|
13 |
<th>City</th> |
14 |
<th width="20%">Country</th> |
15 |
<th width="20%">Continent</th> |
16 |
<th width="25%">Region</th> |
17 |
</tr>
|
18 |
</thead>
|
19 |
<tbody></tbody>
|
20 |
</table>
|
21 |
</div>
|
22 |
</div>
|
23 |
</body>
|
24 |
</html>
|
خیلی سادهست. این فایل در واقع یک جدول را نشان میدهد که آن را با استفاده از اطلاعاتی که از پایگاهداده دریافت میشود پر میکنیم. توجه کنید که برای این مثال من از bootstarp برای ساخت پایه ظاهر صفحه استفاده کردم.
استفاده از صفحهبند
1 |
<?php for( $i = 0; $i < count( $results->data ); $i++ ) : ?> |
2 |
<tr>
|
3 |
<td><?php echo $results->data[$i]['Name']; ?></td> |
4 |
<td><?php echo $results->data[$i]['Country']; ?></td> |
5 |
<td><?php echo $results->data[$i]['Continent']; ?></td> |
6 |
<td><?php echo $results->data[$i]['Region']; ?></td> |
7 |
</tr>
|
8 |
<?php endfor; ?> |
حالا، برای استفاده از کلاس صفحهبند، این کد پیاچپی را به بالای فایل اضافه کنید.
1 |
<?php
|
2 |
require_once 'Paginator.class.php'; |
3 |
|
4 |
$conn = new mysqli( '127.0.0.1', 'root', 'root', 'world' ); |
5 |
|
6 |
$limit = ( isset( $_GET['limit'] ) ) ? $_GET['limit'] : 25; |
7 |
$page = ( isset( $_GET['page'] ) ) ? $_GET['page'] : 1; |
8 |
$links = ( isset( $_GET['links'] ) ) ? $_GET['links'] : 7; |
9 |
$query = "SELECT City.Name, City.CountryCode, Country.Code, Country.Name AS Country, Country.Continent, Country.Region FROM City, Country WHERE City.CountryCode = Country.Code"; |
10 |
|
11 |
$Paginator = new Paginator( $conn, $query ); |
12 |
|
13 |
$results = $Paginator->getData( $page, $limit ); |
14 |
?>
|
این اسکریپت خیلی ساده ست، ما تنها بیان کردیم که نیاز به کلاس صفحهبند داریم. دقت کنید که این کد در نظر میکرد که فایل کلاس صفحهبند در همان پوشهای که index.php
درون آن است قرار دارد. در غیر اینصورت باید مسیر فایل را درست ذکر کنید.
سپس با استفاده از کتابخانه MySQLi ارتباط پایگاهداده را برقرار میکنیم، پارامترهای صفحهبند را از طریق درخواست GET دریافت میکنیم و کوئری را تنظیم میکنیم. از آنجایی که این مقاله در مورد MySQL یا هر چیزی مربوط به آن نیست من در اینجا به جزئیات ارتباط پایگاهداده و کوئری نمیپردازم.
در آخر ما شئ صفحهبند را میسازیم و نتایج را برای صفحه کنونی دریافت میکنیم.
نمایش نتایج
حالا برای نمایش نتایج دریافت شده، این کد را به بدنهی جدول اضافه کنید.
1 |
<?php for( $i = 0; $i < count( $results->data ); $i++ ) : ?> |
2 |
<tr>
|
3 |
<td><?php echo $results->data[$i]['Name']; ?></td> |
4 |
<td><?php echo $results->data[$i]['Country']; ?></td> |
5 |
<td><?php echo $results->data[$i]['Continent']; ?></td> |
6 |
<td><?php echo $results->data[$i]['Region']; ?></td> |
7 |
</tr>
|
8 |
<?php endfor; ?> |
در اینجا، ما داده نتایج را میپیماییم که شامل رکورد شهرها است که برای هر شهر ردیفی در جدول میسازیم.
لینکهای صفحهبند
حالا، جهت نمایش لینکهای صفحهبند، این قطعه کد را به پایین جدول اضافه کنید.
1 |
<?php echo $Paginator->createLinks( $links, 'pagination pagination-sm' ); ?> |
برای متد createLinks در کلاس صفحهبند، پارامتر links و کلاس css مربوط به لینکهای صفحهبند مرتبط با bootstrapt را ارسال میکنیم. در اینجا نتایج صفحهی ساخته شده را میبینید.



جمعبندی
این مقاله تمام چیزی که شما نیاز دارید تا صفحهبندی را در برنامههای خودتان اعمال کنید به شما آموزش داد.
لطفا اگر سوالی، نظری یا بازخوردی دارید درنگ نکنید و در فیلد زیر بنویسید.