تالار گفتمان nCIS.ir

نسخه‌ی کامل: صفحه بندی اخبار سایت شهر خبر
شما در حال مشاهده نسخه آرشیو هستید. برای مشاهده نسخه کامل کلیک کنید.
سلام . میخواستم بدونم سایت شهر خبر http://shahrkhabar.ir از چه روشی برای صفحه بندی اخبارش استفاده می کنه ؟
مثلا چطوری تعیین می کنن که کل اخبار به N صفه تبدیل بشه و در هر صفحه N خبر نشون داده بشه ؟ البته اینو می دونم
که اون صفحات به معنی واقعی وجود ندارن (سوال من در مورد نحوه نمایش اش هست )
با توجه به اینکه برنامه های زیادی رو دیدم و نمی خوام دوستان این مشکل ها رو داشته باشن یکسری توضیحات اضافه تر از نیارهای سوال کننده رو هم می دهم.
- اول اینکه ما نمی دونیم تعداد رکورد های خروجی select  ما چندتاست پس فقط می تونیم بگیم تعداد رکورد ها در هر صفحه چندتا باید باشه. برای صفحه بندی فقط و فقط تعداد کل رکورد ها رو لازم داریم چرا؟ فرض کنید تعداد کل رکوردها 37 تا هست و ما قراره در هر صفحه 10 رکورد داشته باشیم در این صورت تعداد کل صفحات 4 تا خواهد بود.
- دوم اینکه select  رو به چه شکلی بنویسیم و به چه شکلی تعداد کل رکوردها رو برای صفحه بندی بدست بیاریم.
در همه پروژه هایی که تا الان دیدم برای صفحه بندی و نمایش رکورد ها، یکی از دو روش زیر رو استفاده می کنن که من بهتون توصیه نمی کنم چرا؟ بخاطر گرفتن حافظه بیش از اندازه و یا اجرای تکراری یه دستور.
فرض کنید قراره select ی که دارای 3 تا join  هست رو نمایش بدیم افراد یکی از دو روش زیر رو استفاده می کنن
الف) گروه اول میان یه select  با تمام شرط ها و join ها می زنن بدون اینکه از دستور limit استفاده کرده باشن (واقعا شاهکاره!!!)
select users.*, profiles.*, comments.*
from users join profiles ... join comments ... where ...
اینطوری تعداد کل رکورد ها رو توی php با دستور count  بدست میارن و در یه حلقه for میان اطلاعاتی که در اون صفحه لازمه نمایش مدن.
اشکال این روش کمبود حافظه هست خوب فرض کنید در بدترین حالت از ظرفیت فیلدهای یه رکورد استفاده شده باشه مثلا هر رکورد جدول users برابر 512 بایت، profiles برابر 512بایت و comments برابر 1024بایت باشه. 2KB  برای اتصال یک سطر از 3 جدول حالا فکر می کنید یه ram  چه تعداد رکورد می تونه در خودش نگهداری کنه البته در صورت نیاز می تونه از هارد هم استفاده کنه اما ... .
ب) گروه دوم از روش مناسب و معقول تری استفاده می کنن . ابتدا میان دستور select  رو با  limit اجرا می کنن
select users.*, profiles.*, comments.*
from users join profiles ... join comments ... where ... limit 0,10
بعدش در یه select دیگه البته بدون Limit میان از دستور count خود mysql استفاده می کنن
select count(users.*, profiles.*, comments.*)
from users join profiles ... join comments ... where ... 
اشکال این روش اینه که یه دستور با این همه شرط و join  دوباره باید اجرا بشه که از نظر سرعت بهینه نیست.

راه حل: برای رفع این مشکلات از SQL_CALC_FOUND_ROWS در دستور select  استفاده می کنیم
select SQL_CALC_FOUND_ROWS users.*, profiles.*, comments.*
from users join profiles ... join comments ... where ... limit 0,10
SQL_CALC_FOUND_ROWS به mysql  میگه تعداد کل رو بدون limit  برای من یه جا نگهداری کن. بعد از دستور بالا برای بدست آوردن تعداد کل از دستور select FOUND_ROWS() می تونیم استفاده کنیم
select FOUND_ROWS()
حالا مثلا کاربر روی صفحه 5 کلیک کرده ما باید 10 رکورد پنجم از خروجی رو نمایش بدیم.
برای بدست آوردن نقطه شروع دستور limit، شماره صفحه یعنی 5 رو در تعدادی که قراره در هر صفحه نمایش داده بشه یعنی 10 ضرب می کنیم. و با توجه به اینکه اولین رکورد ما در دیتابیس دارای اندیس صفر می باشد پس باید از خروجی بالا یکی کم کنیم یعنی 5*10 منهای 1
select SQL_CALC_FOUND_ROWS users.*, profiles.*, comments.*
from users join profiles ... join comments ... where ... limit 49,10
limit 49,10 یعنی از رکورد 49 شروع کن و 10 تا رکورد رو در خروجی به من نمایش بده.
ضمن تشکر از شما، مورد آخر همون 50 باید باشه نه 49 چون توی صفحه 5 مطالب رکوردهای 40 تا 49 استخراج میشه:

صفحه 1 : مطالب 0 تا 9
صفحه 2 : مطالب 10 تا 19
صفحه 3 : مطالب 20 تا 29
صفحه 4 : مطالب 30 تا 39
صفحه 5 : مطالب 40 تا 49
صفحه 6 : مطالب 50 تا 59
.
.
.
صفحه N : مطالب N-1)*PageSize) تا N-1)*PageSize)+PageSize-1))

بطور خلاصه:
$pageSize = 10;
$page = 1;
if(isset($_GET['page'])) {
    $page = max(1, intval($_GET['page']));
}
$limit = $pageSize;
$offset = ($page - 1) * $pageSize;
$data = mysqli_query("SELECT * FROM `table` LIMIT {$offset},{$limit}");
بله ممنون بخاطر اصلاحتون