شنبه ۲۲ شهریور ۱۴۰۴

Saturday, September 13, 2025 GMT +3:30

صفحه بندی مطالب و محتوا با PHP و MySQL

mysql-php-pagination

یکی از مواردی که دیر یا زود مورد نیاز برنامه نویسان وب خواهد بود، صفحه بندی مطالب و محتوای سایت یا برنامه کاربردی است که در اصطلاح به آن pagination هم می گویند (به معنی تقسیم نمایش محتوای مورد نظر در چند صفحه به جای نمایش آنها در یک صفحه)، ناگفته پیدا است که فواید و لزوم این کار در دسته بندی بهتر و ایجاد محیط کاربری (UI یا User Interface) حرفه ای تر است، البته به جهت پیچیده گی ظاهری این امکان، ممکن است در نگاه نخست طراحی صحیح آن کمی مبهم به نظر برسد، اما با کمی راهنمایی و تمرکز می توان راه حل مشکل را پیدا کرد، به هر صورت در این آموزش قصد داریم تا با هم این مشکل را یک بار برای همیشه حل کنیم!، لذا اگر شما هم علاقمند هستید تا برنامه هایتان را به این روش طراحی کنید، با ادامه مطلب همراه ما باشید.

دیتابیس، جداول و ستون ها


برای صفحه به صفحه کردن مطالب و محتوا، قبل از هر چیز به دیتابیس، جداول و ستون هایی احتیاج داریم که درون خود ردیف هایی از اطلاعات را ثبت کرده باشند، به طور مثال در نمونه کد زیر پرس و جوی فرضی ایجاد یک جدول در پایگاه داده db_test را تنظیم کرده ایم که با اجرای آن در یک فایل PHP، ستون و ردیف های نمونه به دیتابیس افزوده خواهند شد (ساخت دیتابیس، جدول و ستون ها صرفا جهت نمونه است، لذا اگر از قبل مشابه این موارد در دیتابیس برنامه شما وجود دارد، نیازی به ایجاد دوباره آنها نیست).
<?php
//نام میزبان
$db_host = "localhost";
//MySQL نام کاربری
$db_user = "root";
//MySQL کلمه عبور
$db_password = "";
//نام پایگاه داده
$db_name = "db_test";
//نام جدول
$tb_name = "tb_test";

//اتصال به سرور و پایگاه داده
$connect = mysql_connect("$db_host", "$db_user", "$db_password")
or die(mysql_error());

//انتخاب دیتابیس
mysql_select_db("$db_name")
or die(mysql_error());

//تنظیم کاراکترها سازگار با فارسی
$set = mysql_query("SET NAMES 'utf8'")
or die(mysql_error());

//اجرای پرس و جو و ساخت جدول و ستون ها
$create = mysql_query("CREATE TABLE ".$tb_name."(id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), title VARCHAR(255), article MEDIUMTEXT) ENGINE=MyISAM")
or die(mysql_error());

//تنظیم یونیکد utf8
$alter = mysql_query("ALTER TABLE ".$tb_name." DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;")
or die(mysql_error());

//وارد کردن نمونه اطلاعات
for($i = 1; $i <= 5; $i++){
    $insert = mysql_query("INSERT INTO ".$tb_name."(title, article) VALUES ('تیتر $i', 'مقاله $i')")
    or die(mysql_error());
}

//عملیات با موفقیت انجام شد
echo "Successfully Down!";

//پایان اتصال
$close = mysql_close($connect);
?>
نکته 1: به یاد داشته باشیم که قبل از اجرای پرس و جو، باید از طریق برنامه phpMyAdmin دیتابیس db_test را با یونیکد utf8_general_ci ساخته باشیم.
نکته 2: به جهت اینکه آموزش حاضر برای عموم قابل استفاده باشد، از اکستنشن (Extension) اولیه PHP یعنی mysql استفاده شده است، با شبیه سازی پرس و جوها می توانید از PDO یا mysqli نیز استفاده کنید.

تنظیمات اولیه صفحه بندی


پس از ایجاد جدول، ستون و ردیف های اطلاعات، برنامه ما برای صفحه بندی صحیح به سه پارامتر اولیه احتیاج دارد (تعداد آیتم ها در هر صفحه، شماره صفحه درخواستی و شماره id برای تعیین نقطه شروع انتخاب نتایج)، این پارامترها از طریق تعریف متغیر setting (نامی انتخابی و فرضی است)، در یافت شماره صفحه از متد GET و تعیین id شروع (در ادامه خواهیم گفت) مشخص می شوند، متغیری که در قسمت تنظیمات برنامه (متغیر setting) به آن نیاز داریم، نمایانگر تعداد آیتم ها در هر صفحه است (به فرض 2 آیتم در هر صفحه)، لذا در یک فایل php به صورت زیر آن را تعریف می کنیم.
<?php
//تعداد آیتم در هر صفحه
$setting = array(
'paged_item' => 2
);
?>
همان طور که گفتیم، مقادیر این متغیر مشخص کننده این است که در هر صفحه چه تعداد آیتم نمایش داده می شود.
نکته: در اینجا ما از روش آرایه استفاده کرده ایم که به لحاظ کاربردی و اصول برنامه نویسی بهتر است، لذا استفاده از روش های دیگر مانند تعریف مستقیم متغیر و... نیز امکان پذیر است و محدودیتی از این لحاظ وجود ندارد، مهم این است که ما یک متغیر با مقادیری مشخص در اختیار برنامه قرار دهیم تا از آن استفاده کند.
پس از اینکه تعداد آیتم ها در هر صفحه را تعیین کردیم، قاعدتا مورد دیگری به ذهن می رسد که همان شماره صفحه درخواستی است، یعنی برنامه ما باید بداند که کاربر قصد فراخوانی چه صفحه ای را دارد تا متناسب با آن نتایج را از پایگاه داده دریافت و نمایش دهد، این پارامتر از طریق آدرس URL صفحه و به صورت متد GET قابل دریافت است، به فرض اگر آدرس لینک صفحه به صورت زیر باشد.
http://www.yoursite.com/paged_index.php?page=3
مقادیر صفحه فعلی در پارامتر page وجود دارد (عدد 3) که به صورت زیر قابل دریافت در برنامه است.
$page = mysql_real_escape_string($_GET['page']);
نکته: در حالت عادی نیازی به استفاده از تابع mysql_real_escape_string نیست، اما به این جهت که ما از متغیر page در پرس و جوهای دیتابیس استفاده خواهیم کرد، به دلیل ایمن سازی پرس و جو در مقابل حملات MySQL Injection از این تابع استفاده می کنیم.
در آخرین مرحله از تنظیمات اولیه صفحه بندی، نوبت به مشخص کردن شماره id برای شروع یک پرس و جو است، توضیح اینکه در برنامه صفحه بندی از پرس و جویی در دیتابیس خود استفاده خواهیم کرد که با استفاده از LIMIT یک محدوده خاص از ردیف ها را به عنوان نتیجه انتخاب می کند، به فرض نتایج از ردیف شماره 4 به تعداد 2 (تعداد را قبلا در متغیر فرضی setting به صورت آرایه مشخص کردیم)، در این حالت پرس و جوی ما با LIMIT به شکل نمونه زیر خواهد بود.
$query = mysql_query("SELECT id, title, article FROM ".$tb_name." ORDER BY id ASC LIMIT 4, 2")
or die(mysql_error());
ملاحظه می کنید که عدد 4 به عنوان شماره id برای شروع محدوده انتخاب ردیف ها در نظر گرفته شده است (نتایج از 5 شروع شده و شامل خود 4 نمی شود)، اما از آنجایی که ما به دنبال نوشتن یک برنامه داینامیک هستیم که با رفتار کاربر خود را وقف دهد، لذا این عدد نیز باید به صورت داینامیک ایجاد شود، بدین منظور از کد زیر استفاده می کنیم.
//محاسبه شروع انتخاب نتایج
if(empty($page)){
    //پیش فرض
    $page = 1;
}
$start = ($page - 1) * $setting['paged_item'];
توضیح:
- به صورت ساده، کاری که کد بالا برایمان انجام می دهد این است که عدد شروع را برای هر پرس و جو با توجه به صفحه ای که کاربر انتخاب می کند و تعداد آیتم ها در هر صفحه مشخص می کند، به فرض اگر صفحه انتخابی کاربر 3 باشد و تعداد آیتم ها در هر صفحه عدد 2، شماره id شروع با کد بالا به صورت زیر خواهد بود.
$start = (3 - 1) * 2;
که نتیجه برابر 4 خواهد بود و لذا انتخاب ردیف ها از شماره 4 (شامل id شماره 4 نمی شود) به تعداد 2 مورد انجام می شود ( LIMIT 4, 2).
نکته: مشابه همین قابلیت در برنامه phpMyAdmin برای نمایش قسمت خاصی از ردیف ها وجود دارد و جهت آشنایی بیشتر می توانید آن را امتحان کنید.

نحوه پرس و جو از دیتابیس در هنگام صفحه بندی


همان طور که در قسمت تنظیمات اولیه دیدیم، برای اینکه بتوانیم سیستم صفحه بندی را به نحو صحیح ایجاد کنیم، پرس و جوی اصلی ما باید از قابلیت LIMIT با دو عدد (id شروع انتخاب ردیف ها و تعداد آیتم) استفاده کند، از آنجایی که سیستم ما به صورت داینامیک عمل خواهد کرد، لذا به جای قرار دادن مستقیم اعداد، باید از متغیرهایی که مقادیر را در خود دارند استفاده کنیم، به مثال زیر توجه کنید.
//اجرای پرس و جوی داینامیک و دریافت مقادیر
$query = mysql_query("SELECT id, title, article FROM ".$tb_name." ORDER BY id ASC LIMIT $start, ".$setting['paged_item']."")
or die(mysql_error());
توضیح:
- با توجه به این مثال، اگر کاربر از طریق متد GET صفحه ای را انتخاب نکرده باشد، به صورت پیش فرض صفحه شماره 1 انتخاب می شود (page = 1)، لذا شماره id از صفر (شامل خود صفر نمی شود) شروع و به 2 مورد ختم می شود (یعنی id شماره 1 و 2 برای صفحه اول انتخاب می شوند).
- قسمت LIMIT در این مثال (با فرض صفحه 1) به صورت LIMIT 0, 2 است، یعنی id شماره 1 و 2 انتخاب می شود، اما اگر نوع ORDER BY به صورت DESC باشد، انتخاب از آخر و بیشترین مقدار انجام می شود و id شماره 5 و 4 انتخاب می شوند.

بررسی اولیه برای ایجاد لینک های صفحه بندی


هرچند درک مواردی که تا این لحظه گفتیم به خودی خود اهمیت زیادی دارد، اما مهم تر از آنها نوشتن سیستمی برای ایجاد لینک های داینامیک است تا شماره صفحات و مواردی مانند صفحه قبل، صفحه بعد، صفحه اول و صفحه آخر را به دقت چاپ کند، البته با کسب تجربه و مهارت بیشتر در برنامه نویسی PHP و با اندکی خلاقیت می توان این کار را به شکل های مختلف و به صورت سفارشی انجام داد، اما جهت نمونه یک مورد را در ادامه بررسی می کنیم، به طور خلاصه در این قسمت نیازمند موارد زیر هستیم:
- تعداد کل ردیف های موجود در دیتابیس (به فرض 5 مورد).
- تعداد کل صفحاتی که ایجاد می شوند (به فرض 3 صفحه).
- تعداد لینک صفحه در قسمت نمایش صفحات (به فرض لینک 4 صفحه).
- مقادیر لینک صفحه اول (به فرض 1).
- مقادیر لینک صفحات میانی (به فرض 2).
- مقادیر لینک صفحه آخر (به فرض 3).
- مقادیر لینک صفحه قبل (در صورت وجود).
- مقادیر لینک صفحه بعد (در صورت وجود).
برای به دست آوردن تعداد کل ردیف های موجود در دیتابیس یک پرس و جو مشابه پرس و جوی اصلی برنامه می نویسیم، با این تفاوت که این بار از LIMIT استفاده نخواهیم کرد (تا همه موارد انتخاب شوند)، به مثال زیر توجه کنید.
//پرس و جو تعداد کل ردیف ها
$total = mysql_query("SELECT id FROM ".$tb_name."")
or die(mysql_error());
//مجموع
$count = mysql_num_rows($total);
نکته: برای به دست آوردن تعداد کل ردیف ها می توان از روش های مختلفی (مانند استفاده از تابع COUNT که جزء توابع تجمیعی یا Aggregation در MySQL است) نیز استفاده کرد.
پس از اینکه تعداد کل ردیف ها را به دست آوردیم، باید بررسی کنیم و ببینیم که آیا نیاز به صفحه بندی است یا خیر، به طور مثال اگر تعداد آیتم های دیتابیس، از تعداد آیتم های بخش تنظیمات کمتر باشد، نیازی به صفحه بندی نیست، چون در واقع صفحه ای وجود ندارد، اما اگر این طور نبود حداقل دو صفحه خواهیم داشت، به هر صورت این هدف با مقایسه زیر دست یافتنی است.
//بررسی نیاز به صفحه بندی
if($count - $setting['paged_item'] > 0){
}
else{
    echo 'صفحه ای وجود ندارد!';
}
با فرض وجود صفحات، تعداد آنها را به صورت زیر محاسبه می کنیم.
//بررسی نیاز به صفحه بندی
if($count - $setting['paged_item'] > 0){
    //تعداد صفحه
    $paged_total = ceil($count / $setting['paged_item']);
}
نکته: تعداد صفحات را با تقسیم تعداد ردیف های موجود در دیتابیس (در اینجا 5) بر تعداد آیتم در هر صفحه (در اینجا 2) و با گرد کردن توسط تابع ceil به دست می آوریم (نتیجه برابر 3 می شود).
پس از مشخص شدن تعداد کل صفحات، صفحه آخر ما همان تعداد کل صفحات است (به طور مثال در اینجا چون 3 صفحه داریم، آخرین صفحه می شود 3).
صفحه اول همیشه صفحه 1 است، لذا نیاز به تعریف آن نیست، اما صفحات میانی و قبل و بعد باید به صورت داینامیک ساخته شوند که در ادامه خواهیم دید.
برای ادامه کار، دو پارامتر زیر را نیز به کد خود اضافه می کنیم.
//بررسی نیاز به صفحه بندی
if($count - $setting['paged_item'] > 0){
    //تعداد صفحه
    $paged_total = ceil($count / $setting['paged_item']);
    //صفحه آخر
    $paged_last = $paged_total;
    //صفحات میانی
    $paged_middle = $page + 4;
    //شروع صفحه بندی
    $paged_start = $paged_middle - 4;
}
در اینجا شروع صفحه بندی به برنامه ما کمک می کند تا صفحات بعدی و قبلی را از صفحه انتخابی کاربر محاسبه کند.
قسمت مربوط به صفحات میانی، تعداد صفحات بعدی (4 صفحه بعدی) را با توجه به صفحه انتخابی کاربر مشخص می کند.
نکته: درک این قسمت ممکن است در نگاه نخست کمی پیچیده به نظر برسد، اگر این طور بود، تنها کافی است از نمونه کدها پیروی کنید، نیازی نیست الزاما مفهوم آنها را نیز در نگاه نخست متوجه شوید.

ایجاد لینک های صفحه به صفحه


در قسمت پایانی کار لینک صفحات را با استفاده از بلاک های div یا span و استایل CSS در کنار هم قرار می دهیم تا کاربر بتواند با انتخاب آنها، بین صفحات مختلف یک مورد را انتخاب کند.
//بررسی نیاز به صفحه بندی
if($count - $setting['paged_item'] > 0){
    //تعداد صفحات
    $paged_total = ceil($count / $setting['paged_item']);
    //صفحه آخر
    $paged_last = $paged_total;
    //صفحات میانی
    $paged_middle = $page + 4;
    //شروع صفحه بندی
    $paged_start = $paged_middle - 4;
    
    //ایجاد لینک صفحه نخست
    if($page > 1){
        //اگر صفحه درخواستی بزرگتر از 1 بود
        $paged_result = '<div class="paged-link"><a href="paged_index.php?page=1" title="صفحه نخست">نخست</a></div>'."\n";                            
    }
    //غیر فعال کردن لینک صفحه نخست اگر صفحه درخواستی برابر 1 بود
    else{
        $paged_result = '<div class="paged-link-off">نخست</div>'."\n";                                    
    }
    
    //ایجاد لینک صفحه قبلی
    if($page > 1){
        //محاسبه لینک صفحه قبلی        
        $paged_perv = $page - 1;
        //ایجاد لینک صفحه قبلی
        $paged_result .= '<div class="paged-link"><a href="paged_index.php?page='.$paged_perv.'" title="صفحه قبلی">قبلی</a></div>'."\n";
    }
    //غیر فعال کردن لینک صفحه قبلی اگر صفحه انتخابی برابر 1 بود
    else{
        $paged_result .= '<div class="paged-link-off">قبلی</div>'."\n";
    }
    
    //ایجاد لینک صفحات میانی، شروع از دو شماره قبل
    for ($i=$paged_start-2; $i<=$paged_middle; $i++){
        //ایجاد لینک در صورتی که صفر، منفی یا از آخرین صفحه بیشتر نباشد
        if ($i > 0 && $i <= $paged_last){
            //در حالت انتخاب شده
            if($i == $page){
                $paged_result .= '<div class="paged-link-selected"><a href="paged_index.php?page='.$i.'" title="صفحه '.$i.'">'.$i.'</a></div>'."\n";
            }
            //در حالت عادی
            else{
                $paged_result .= '<div class="paged-link"><a href="paged_index.php?page='.$i.'" title="صفحه '.$i.'">'.$i.'</a></div>'."\n";
            }
        }
    }
    
    //نمایش لینک صفحات بعدی
    if($page <= $paged_last - 1){
        //محاسبه لینک صفحه بعدی
        $paged_next = $page + 1;
        //ایجاد لینک صفحه بعدی        
        $paged_result .= '<div class="paged-link"><a href="paged_index.php?page='.$paged_next.'" title="صفحه بعدی">بعدی</a></div>'."\n";
    }
    //غیر فعال کردن لینک صفحه بعدی اگر صفحه انتخابی برابر صفحه آخر بود
    else{
        $paged_result .= '<div class="paged-link-off">بعدی</div>'."\n";
    }
    
    //لینک صفحه آخر
    if($page <= $paged_last - 1){
        $paged_result .= '<div class="paged-link"><a href="paged_index.php?page='.$paged_last.'" title="صفحه آخر">آخر</a></div>'."\n";
    }
    //غیر فعال کردن لینک صفحه آخر اگر صفحه انتخابی برابر صفحه آخر بود
    else{
        $paged_result .= '<div class="paged-link-off">آخر</div>'."\n";
    }
    
    //اطلاعات صفحات
    $paged_result .= '<div class="paged-link-info">&raquo; صفحه: '.$page.' از '.$paged_total.'</div>'."\n";
    //خروجی
    echo $paged_result;                
}
else{
    echo 'صفحه ای وجود ندارد!'."\n";
}
در کدهای بالا به صورت داینامیک لینک صفحاتی که باید به کاربر نشان داده شود را ایجاد و به متغیر فرضی paged_result آن را اختصاص داده ایم، مسلما برای اینکه لینک ها به درستی ایجاد شوند، نیاز به پاره ای محاسبات و استفاده از حلقه های for است که به جهت مقدماتی بودن مبحث، از تکرار آن صرف نظر می کنیم.
نکته: با خروجی گرفتن از متغیر paged_result، می توانید لینک صفحات را نمایش دهید.

استایل CSS برای  بلاک های صفحه بندی


همان طور که گفتیم، لینک های صفحات در بلاک های div یا span ساخته می شوند که برای نمایش صحیح آنها نیاز به استایل CSS است، این استایل را برای بلاک های نمونه بالا به صورت زیر تنظیم کرده ایم.
<style type="text/css">
.paged-link{
    display:inline-block;
    line-height:14px;
    float:right;
    margin:2px;
}
.paged-link a{
    display:inline-block;
    border:#06C 1px solid;
    padding:2px;
    text-decoration:none;
}
.paged-link a:hover{
    border:#900 1px solid;
}
.paged-link-selected{
    display:inline-block;
    line-height:14px;
    float:right;
    margin:2px;
}
.paged-link-selected a{
    display:inline-block;
    border:#900 1px solid;
    padding:2px;
    text-decoration:none;
}
.paged-link-selected a:hover{
    border:#900 1px solid;
}
.paged-link-off{
    display:inline-block;
    border:#06C 1px solid;
    padding:2px;
    color:#CCC;
    line-height:14px;
    float:right;
    margin:2px;
}
.paged-link-info{
    display:inline-block;
    float:left;
    padding:2px;
    color:#666;
    line-height:14px;
    margin:2px;
    font-size:11px;
}
</style>

نتیجه نهایی صفحه بندی و دانلود فایل ها


برای جمع بندی مباحثی که مطرح کردیم، بد نیست نمونه کدها را به صورت کلی در یک فایل قرار دهیم، ضمن اینکه برای تست و راحتی بیشتر، کدها و مثال مطرح شده در قالب یک فایل zip جهت دانلود قرار داده شده است.
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>وبگو | صفحه به صفحه کردن محتوا در PHP</title>
<!-- https://webgoo.ir -->
<link rel="stylesheet" href="paged_style.css">
</head>
<body>
<?php
//تعداد آیتم در هر صفحه
include_once('paged_setting.php');

//نام میزبان
$db_host = "localhost";
//MySQL نام کاربری
$db_user = "root";
//MySQL کلمه عبور
$db_password = "";
//نام پایگاه داده
$db_name = "db_test";
//نام جدول
$tb_name = "tb_test";

//اتصال به سرور و پایگاه داده
$connect = mysql_connect("$db_host", "$db_user", "$db_password")
or die(mysql_error());

//انتخاب دیتابیس
mysql_select_db("$db_name")
or die(mysql_error());

//تنظیم کاراکترها سازگار با فارسی
$set = mysql_query("SET NAMES 'utf8'")
or die(mysql_error());

//دریافت صفحه درخواستی
@$page = mysql_real_escape_string($_GET['page']);

//محاسبه شروع انتخاب نتایج
if(empty($page)){
    //پیش فرض
    $page = 1;
}
$start = ($page - 1) * $setting['paged_item'];

//اجرای پرس و جوی داینامیک و دریافت مقادیر
$query = mysql_query("SELECT id, title, article FROM ".$tb_name." ORDER BY id ASC LIMIT $start, ".$setting['paged_item']."")
or die(mysql_error());

//چاپ خروجی
while($row = mysql_fetch_array($query)){
    $id = $row['id'];
    $title = $row['title'];
    $article = $row['article'];
    echo 'مطلب شماره: '.$id.' '.$title.' '.$article.'<br />'."\n";
}

//پرس و جوی تعداد کل ردیف ها
$total = mysql_query("SELECT id FROM ".$tb_name."")
or die(mysql_error());
//مجموع
$count = mysql_num_rows($total);

//بررسی نیاز به صفحه بندی
if($count - $setting['paged_item'] > 0){
    //تعداد صفحات
    $paged_total = ceil($count / $setting['paged_item']);
    //صفحه آخر
    $paged_last = $paged_total;
    //صفحات میانی
    $paged_middle = $page + 4;
    //شروع صفحه بندی
    $paged_start = $paged_middle - 4;
    
    //ایجاد لینک صفحه نخست
    if($page > 1){
        //اگر صفحه درخواستی بزرگتر از 1 بود
        $paged_result = '<div class="paged-link"><a href="paged_index.php?page=1" title="صفحه نخست">نخست</a></div>'."\n";                            
    }
    //غیر فعال کردن لینک صفحه نخست اگر صفحه درخواستی برابر 1 بود
    else{
        $paged_result = '<div class="paged-link-off">نخست</div>'."\n";                                    
    }
    
    //ایجاد لینک صفحه قبلی
    if($page > 1){
        //محاسبه لینک صفحه قبلی        
        $paged_perv = $page - 1;
        //ایجاد لینک صفحه قبلی
        $paged_result .= '<div class="paged-link"><a href="paged_index.php?page='.$paged_perv.'" title="صفحه قبلی">قبلی</a></div>'."\n";
    }
    //غیر فعال کردن لینک صفحه قبلی اگر صفحه انتخابی برابر 1 بود
    else{
        $paged_result .= '<div class="paged-link-off">قبلی</div>'."\n";
    }
    
    //ایجاد لینک صفحات میانی، شروع از دو شماره قبل
    for ($i=$paged_start-2; $i<=$paged_middle; $i++){
        //ایجاد لینک در صورتی که صفر، منفی یا از آخرین صفحه بیشتر نباشد
        if ($i > 0 && $i <= $paged_last){
            //در حالت انتخاب شده
            if($i == $page){
                $paged_result .= '<div class="paged-link-selected"><a href="paged_index.php?page='.$i.'" title="صفحه '.$i.'">'.$i.'</a></div>'."\n";
            }
            //در حالت عادی
            else{
                $paged_result .= '<div class="paged-link"><a href="paged_index.php?page='.$i.'" title="صفحه '.$i.'">'.$i.'</a></div>'."\n";
            }
        }
    }
    
    //نمایش لینک صفحات بعدی
    if($page <= $paged_last - 1){
        //محاسبه لینک صفحه بعدی
        $paged_next = $page + 1;
        //ایجاد لینک صفحه بعدی        
        $paged_result .= '<div class="paged-link"><a href="paged_index.php?page='.$paged_next.'" title="صفحه بعدی">بعدی</a></div>'."\n";
    }
    //غیر فعال کردن لینک صفحه بعدی اگر صفحه انتخابی برابر صفحه آخر بود
    else{
        $paged_result .= '<div class="paged-link-off">بعدی</div>'."\n";
    }
    
    //لینک صفحه آخر
    if($page <= $paged_last - 1){
        $paged_result .= '<div class="paged-link"><a href="paged_index.php?page='.$paged_last.'" title="صفحه آخر">آخر</a></div>'."\n";
    }
    //غیر فعال کردن لینک صفحه آخر اگر صفحه انتخابی برابر صفحه آخر بود
    else{
        $paged_result .= '<div class="paged-link-off">آخر</div>'."\n";
    }
    
    //اطلاعات صفحات
    $paged_result .= '<div class="paged-link-info">&raquo; صفحه: '.$page.' از '.$paged_total.'</div>'."\n";
    //خروجی
    echo $paged_result;                
}
else{
    echo 'صفحه ای وجود ندارد!'."\n";
}

//پایان اتصال
$close = mysql_close($connect);
?>
</body>
</html>
دانلود نمونه فایل های صفحه بندی
دسته بندی: آموزش کاربردی » MySQL
related مطالب بیشتر:
ایجاد لینک دانلود مدت دار با PHP و MySQL
نحوه رسم چارت و نمودار آماری با PHP و MySQL
آموزش حذف گروهی اطلاعات از MySQL با استفاده از چک باکس
جستجو در مطالب سایت با استفاده از MySQL Full-Text
ساخت فید آر اس اس (RSS Feed) با استفاده از PHP و MySQL
دیدگاه
more ۹۳ دیدگاه برای این مطلب ارسال شده است.
more چینش دیدگاه ها به ترتیب از جدیدترین به قدیمی ترین است.
ایران
۱۰:۳۲ ۱۴۰۲/۰۱/۱۳
سلام و وقت بخیر.
من یه پروژه ای دارم که میخوام از دو تا جدول که شبیه زیر هستن اطلاعات رو سورت کنم و نمایش بدم.
جدول A مربوط میشه به کالا و توضیحات هر کالا به همراه تاریخ آپدیت مشخصات هر کالا جدول B مربوط میشه به قیمت کالا در جدول A که ممکنه یه کالا چند تا قیمت داشته باشه و یه کالا هم کلا قیمت نداشته باشه.
حالا می خوام اطلاعات اینطوری سورت بشه که اطلاعات جدول A به ترتیب تاریخ آپدیت نمایش داده بشه اما با اولویت قیمت در جدول B مثلا اگه کالایی در جدول B قیمت نداشت در آخر بیاد و اگه قیمت داشت در اول بیاد.
همچنین با این جدول ها چطور میشه کالا ها رو بر اساس قیمت کم به زیاد یا برعکس سورت کرد؟ چون ممکنه که یه کالا چند تا قیمت داشته باشه و باید قاعدتا میانگین قیمت در نظر گرفته بشه (یا کمترین قیمت یا بیشترین قیمت)
جدول A (کالاها)
کالا موبایل                 تاریخ آپدیت 1403
کالا لپ تاپ تاریخ آپدیت 1401
کالا هدفون تاریخ آپدیت 1399
کالا لوازم تاریخ آپدیت 1402
جدول B (قیمت ها)
قیمت 1000               مربوط به لپ تاپ
قیمت 2000 مربوط به موبایل
قیمت 1000 مربوط به لپ تاپ
قیمت 3000 مربوط به هدفون
قیمت 5000 مربوط به لپ تاپ
قیمت 6000 مربوط به هدفون
حالا اطلاعات اینطوری بیاد (سورت بر اساس تاریخ آپدیت)
1- موبایل      قیمت از 2000
2- لپ تاپ قیمت از 1000
3- هدفون قیمت از 3000
4- لوازم بدون قیمت
یا اینطوری (بر اساس قیمت کم به زیاد)
1- لپ تاپ    قیمت از 1000
2- موبایل قیمت از 2000
3- هدفون قیمت از 3000
4- لوازم بدون قیمت
یا اینطوری (بر اساس قیمت زیاد به کم)
1- هدفون     قیمت از 3000
2- موبایل قیمت از 2000
3- لپ تاپ قیمت از 1000
4- لوازم بدون قیمت
ممنونم ببخشید سوالم خیلی طولانی شد.
ساختار و اطلاعات جداول قابل تست ارائه نکرده اید، در هر صورت با فرض وجود دو جدول a و b با نمونه ساختار زیر:
جدول tbl_a:
id type date
جدول tbl_b:
id type stuff price
برای استخراج اطلاعات در حالت اول یعنی بر اساس تاریخ جدول tbl_a نمونه پرس و جوی زیر کاربرد دارد:
SELECT tbl_b.type, tbl_b.stuff FROM tbl_b 
INNER JOIN
tbl_a ON tbl_a.type = tbl_b.type
ORDER BY tbl_a.date DESC
برای حالت دوم و سوم یعنی مرتب سازی بر اساس قیمت جدول tbl_b نمونه پرس و جوی زیر قابل استفاده است:
SELECT tbl_b.type, tbl_b.stuff, tbl_b.price FROM tbl_b 
INNER JOIN
tbl_a ON tbl_a.type = tbl_b.type
ORDER BY tbl_a.type, tbl_b.price ASC
که برای تغییر مرتب سازی صعودی و نزولی به جای عبارت ASC می توانیم از DESC استفاده کنیم.
محمدرضا
۰۱:۲۶ ۱۴۰۱/۰۷/۱۰
با سلام و با تشکر از شما استاد
ببنید این فیلد توی دیتابیس ممکن است به شیوه های اینطوری ذخیره بشه
$text = 'a:2:{s:11:"canEditFile";i:0;s:14:"canEditDetails";i:0;}';
$text = 'a:2:{s:12:"canEditFile";i:0;s:15:"canEditDetails";i:0;}';
$text = 'a:2:{s:10:"canEditFile";i:0;s:13:"canEditDetails";i:0;}';
میخوام یه الگو داشته باشم این متن اگه بصورت الگو بود تبدیل به هیچی کنم! یعنی خالی کنم. اگه متن ثابت بشه replace می کنم و میگم اگه متن اینطوری بود متن رو با replace پاک کن که فیلد خالی بشه! ولی همونطوری که گفتم متن داخل فیلد این قسمتهاش عوض می شه و من وقتی جایی رو تغییر میدم اگه i:0 شد یعنی کارم با این فیلد تموم شده و میخوام فیلد رو پاک کنم! فقط عددهایی که گفتم تغییر می کنن و باید الگو رو جوری داشته باشم که اون عددها هرچی بودن به شرطی که i:0 بود فیلد رو باهاش خالی کنم.
وقتی i:1 است یعنی میشه جدول رو تغییر داد، حالا وقتی جدول رو تغییر دادم i:0 میشه و دیگه کارم با اون فیلد تموم میشه، من میخوام الگو رو جوری داشته باشم که اگه i:0 بودن بقیه اعداد داخل متن که گفتم تݝییر می کنن هرچی بودن replace کنم. راستی برای جواب قبلی هم متوجه منظورتون شدم و راهنمایی بسیار خوبی بود، ازتون بسیار ممنون و سپاسگزارم
بازم تشکر از شما
خواهش، می توانید نمونه کد زیر را با حالت های مختلف تست و در صورت عملکرد مورد انتظار، استفاده کنید:
<?php
$text = 'a:2:{s:11:"canEditFile";i:0;s:14:"canEditDetails";i:0;}';
$pattern = '/a:2:{s:([0-9]+):"canEditFile";i:0;s:([0-9]+):"canEditDetails";i:0;}/i';
$text = preg_replace($pattern, '', $text);
var_dump($text);
?>
محمدرضا
۰۸:۳۳ ۱۴۰۱/۰۷/۰۹
ببخشید یه سوال دیگه هم دارم
آیا امکان داره با استفاده از کوئری توی php یه متنی رو به یه مقدار دیگه تغییر داد؟ مثلا من می خوام وقتی یه اکشنی رو اجرا میکنم فرضا "این یک مطلب تست است" رو تغییر بدم به "این یک مطلب تست نیست"! یعنی فقط است رو به نیست تغییر بدم! توی دیتابیس مشکلی ندارم که کوئری رو اجرا کنم ولی می خوام اینکار رو با php انجام بدم و بهش نیاز دارم کل فیلد رو می تونم با کوئری عوض کنم ولی من احتیاج به این دارم که یه قسمت از متن رو به یه چیز دیگه تغییر بدم
ممنون می شم راهنمایی کنید.
Yii::app()->db->createCommand()->update('news',array('extra'=>'این یک مطلب تست نیست'),"id={$news->id}");
با تشکر
ساده ترین روش تعریف رشته داخل آرایه به صورت یک متغیر خارجی و استفاده از توابعی مانند str_replace قبل از تنظیم آرگیومنت متد update است، به فرض:
$extra = 'sample text? yes!';
$extra = str_replace('sample text? yes!', 'sample text? no!', $extra);
Yii::app()->db->createCommand()->update('news', array('extra'=>$extra), "id={$news->id}");
اگر به هر دلیل نتوانیم به پارامترهای متد update خارج از متد دسترسی پیدا کنیم کار سخت می شود چون از فریم ورک Yii استفاده شده و دسترسی به متدهای این فریم ورک و اعمال تغییرات دلخواه در کدنویسی ها شاید ساده نباشد.
محمدرضا
۰۸:۲۳ ۱۴۰۱/۰۷/۰۹
با سلام و خسته نباشید
من یه متن دارم:
$text = 'a:2:{s:11:"canEditFile";i:0;s:14:"canEditDetails";i:0;}';
عددها برای هر مطلب تغییر می کنند، من می خوام یه الگو preg_replace داشته باشم که عددهایی داخل اینها هرچی بود به یه متن دیگه تبدیل کنم. اعداد متغییر اینها هستند:
a:2
s:11
s:14
بقیه متن ثابت هستند.
با تشکر
لطفا دقیقا مشخص کنید کل رشته متغیر text را می خواهید به یک متن دیگر تبدیل کنید یا صرفا هر عدد را می خواهید با یک عبارت دیگر جایگزین کنید؟ اگر یک نمونه خروجی مد نظر هم درج کنید به نوشتن الگو کمک می کند.
سینا امیری
۰۳:۲۲ ۱۴۰۱/۰۶/۲۵
با سلام و خسته نباشید
من می خواهم از لینک:
https://mysite.com/xmain/allnews/tag/%D9%BE%DB%8C%D8%B4+%D8%AF%D8%A8%D8%B3%D8%AA%D8%A7%D9%86%DB%8C
قسمت tag این لینک رو دربیارم ولی هرکاری می کنم جواب نمیده به این صورت ها امتحان کردم ولی اصلا قسمت tag رو شناسایی نمی کنه!
function actionTag() {
$tags = $_GET['params1'];
و
function actionTag()
{
if(isset($_GET['tag']))
$tags = $_GET['tag'];
else
$tags = $_GET['tag'];
میشه راهنمایی کنید؟
با تشکر
لینک شما به صورت استاتیک است یعنی در سرور ابتدا باید در فایل htaccess تبدیل به حالت داینامیک شود تا پارامترها از طریق متد GET قابل دریافت باشند، معمولا باید در ریشه سایت یک فایل htaccess موجود باشد و باید ببینید داخل این فایل پارامتر tag چطور بازنویسی (Rewrite) شده است یا خیر، همچنین تابعی که نوشتید ایراداتی دارد و بخش return مشخص نیست یا اینکه کامل درج نکرده اید.
ریحانه
۱۶:۱۸ ۱۴۰۱/۰۶/۲۱
سلام.
توی بعضی از سایت ها، برای نمایش متن خاص از یه ترفند استفاده میکنند که قالب به هم نریزه و متن بر اساس عرض سایز نمایشگر کاربر کم و زیاد میشه و علامت .... در انتهای متن میاد. فکر میکنم این ترفند بر اساس جاوا اسکریپت باشه. مثلاً اگه ابعاد عرض مرورگر رو کم و زیاد کنیم متن این شکلی میشه.
تست متن جهت نمایش ....
تست متن جهت ...
تست متن ...
تست متن جهت نمایش کامل.
این ترفند برای نمایش داده در جدول خیلی کاربردی هست، خواستم ببینم شما میدونید چطور باید این رفتار متن رو پیاده کرد؟
اگر یک نمونه صفحه هم درج می کردید بهتر بود، به هر صورت برای درج سه نقطه در انتهای متن در شرایطی که فضای کافی برای نمایش آن وجود ندارد خاصیت text-overflow در CSS وجود دارد که باید مقادیر ellipsis داشته باشد، مثال:
<style>
.text-block {
width : 100px;
overflow:hidden;
display:inline-block;
text-overflow: ellipsis;
white-space: nowrap;
direction: rtl;
}
</style>
<div class="text-block">
تست متن جهت نمایش تست متن جهت نمایش تست متن جهت نمایش تست متن جهت نمایش تست متن جهت نمایش
</div>
ریحانه
۱۵:۴۲ ۱۴۰۱/۰۶/۲۱
سلام.
سپاس فراوان از پاسخگویی
ریحانه
۰۷:۳۸ ۱۴۰۱/۰۶/۲۰
سلام. وقت بخیر
من قصد دارم توی فرم تماس با ما در سایتم از ادیتور متن مثل ckeditor استفاده کنم. قبلاً از textarea معمولی استفاده می کردم و برای حفظ امنیت ذخیره کردن و نمایش دادن اطلاعات ، داده ورودی textarea رو با کدهایی مثل strip_tag در php فیلتر میکردم.
حالا که قصد دارم از ادیتور استفاده کنم، (چون ادیتور کدهای html خروجی میده) نمی تونم از strip_tag و ... استفاده کنم. برای این مورد بهترین راه حل چیه که از حملات sql injection و ... جلوگیری کنیم و داده ها امن و خوب نمایش داده بشه؟
الان من بدون هیچ فیلتری اطلاعات فرم تماس با ما رو که از ckeditor گرفته شده در دیتابیس ذخیره میکنم و موقع لود هم بدون کاری خاصی همون رو نمایش میدم. (می‌دونم که این کار اشتباه هست و احتمال هک کردن وجود دارد.)
نوع حملات هکرها متفاوت است و برای هر شکل آسیب پذیری احتمالی باید راه حل مخصوصی استفاده کنیم، به فرض برای جلوگیری از نفوذ به دیتابیس (SQL Injection) بهترین شیوه استفاده از Bind و Prepared Statements است که لازمه آن کدنویسی با اکستنشن های MySQLi یا PDO می باشد، این راه حل مرحله ذخیره سازی را ایمن می کند اما در هنگام چاپ داده ها در مرورگر باید مراقب حملاتی مثل XSS باشیم، در این شیوه مهاجم یک تکه کد جاوا اسکریپتی را که از قبل در محتوای شما ذخیره کرده در خروجی سایت چاپ می کند و می تواند کنترل فرایندهای مرورگر کاربران را دستکاری کند، معمولا تگ script یا iframe برای این کار استفاده می شود که راحتترین راه حل ممکن برای خنثی سازی خطر هک استفاده از توابعی مانند htmlspecialchars یا strip_tags در هنگام چاپ خروجی است، این توابع تمام تگ های HTML را تبدیل و بی اثر می کنند و اگر وجود تگ خاصی مانند br و... مد نظر شما است می توانید استثناء ایجاد کنید به فرض:
echo strip_tags($text, '<p><br><a>');
البته در سایت مرجع PHP گفته شده که به تابع strip_tags برای دفع حملات XSS نباید اکتفا شود و به استفاده از htmlspecialchars توصیه شده، در این صورت یک راه حل این است که تگ های مجاز را قبل از ذخیره سازی در دیتابیس از فیلتر تابعی عبور داده و به شکل دیگری تبدیل کنیم به فرض:
[[br]]
و سپس هنگام چاپ در خروجی به حالت اول برگردانیم:
<br>
ابوالفضل
۰۰:۳۵ ۱۳۹۶/۱۱/۲۴
سلام کد نویسی قسمت صفحه بندی سیستم مدیریت محتوای من اینجوریه:
حذف شد
اما این سیستم همه صفحات رو پشت سر هم مینویسه چه تغییری باید انجام بدم تا مثل شیوه صفحه بندی شما بشه
برای اصلاح این کد نیاز به تست و آزمایش و خطا است، در هر صورت به نظر می رسد متغیر numpages تعداد کل صفحات و متغیر pageNum مقدار صفحه جاری است که بر همین اساس می توان کد را بر طبق الگو و ساختار آموزش بازنویسی کرد.
sina
۱۴:۳۰ ۱۳۹۶/۱۰/۱۵
مطالب خیلی قدیمیه و بعضی از کدها منسوخ شده خب حالا کسی که از php چیزی ندونه اینا رو کپی میکنه تو پروژه اش و با ارورهای زیادی که روبرو میشه گیج میشه لطفا بروزرسانی کنید تا همه افراد بتوننن استفاده کننند. ممنون از سایت خوبتون. فقط لطفا زودتر آپدیت کنید.
بله، این نکته در کادر بالای مطالب سایت توضیح داده شده، مطالب به صورت تدریجی در حال بازبینی و ویرایش هستند.
۱۵:۵۹ ۱۳۹۶/۰۶/۲۰
سلام و خسته نباشید
یه سوال داشتم در همین مبحث بطور مثال یک جدول ثبت اطلاعات داریم...
اگر یک ستون مخصوص جنسیت داشته باشیم و بخواهیم اطلاعات مرد و زن رو جدا از هم چاپ کنه به چه صورت میشه؟
لطفا آموزش دسته بندی مطالب رو هم قرار بدید
برای این منظور می توانید در قسمت WHERE شرط مورد نظر را اضافه کنید، به طور مثال:
SELECT * FROM tbl WHERE gender = 'male' LIMIT 15
بهمن
۱۷:۳۹ ۱۳۹۵/۱۲/۰۶
ممنون از پاسختون . منم الان مشکلی که آقای هادی ملکیان پرسیدند دارم . از طریق فرم جستجو مقداری که جستجو شده از طریق متد post به صفحه جستجو ارسال میگردد . اما وقتی نتیجه جستو چند صفحه باشد و بخواهیم به صفحه دوم برویم میره به صفحه ایی که خودمون گفتیم اگر پارامتر جستجو رو نگرفته باشد دایرکت بشه اونجا.
شما گفتین کد های سورس سمت سرور باید ویرایش بشه ، لطفا در این مورد بیشتر راهنمایی بفرمایید ، چون اینطوری صفحه بندی صفحه جستجو کاملا بی معنی میشه
همان طور که در پاسخ قبلی گفته شده، در هر درخواست جستجو باید پارامترهای مربوط به عبارت جستجو شده و شماره صفحه به سرور (برنامه ما) به عنوان ورودی داده شود، این ورودی در صفحات وب یا از طریق متد POST است، به طور مثال با تنظیم URL قسمت action یک form در HTML، یا از طریق متد GET، به طور مثال و در حالت معمول از طریق پارامترهای URL درخواستی، به فرض آدرس زیر را در نظر بگیرید:
http://webgoo.ir/?search=your+query&page=4
در این نمونه آدرس، عبارت جستجو شده در پارامتر search و صفحه درخواستی در پارامتر page وجود دارد، در هنگام صفحه بندی باید با کدنویسی داینامیکی (که در آموزش حاضر به صورت مفصل توضیح داده شده)، این پارامترها را در لینک های صفحه بندی داشته باشید (یعنی از متد GET استفاده کنید)، لطفا آموزش را به صورت کامل مطالعه کنید، همه موارد لازم به همراه نمونه کد گفته شده!
bahman
۱۵:۰۵ ۱۳۹۵/۱۱/۱۸
سلام و خسته نباشید . آموزشتون برای نمایش 5 آیتم در هر صفحه رو پیاده کردم . من یک جدولی دارم که با این ترتیب نمایش باید 80 تا صفحه بشه . مشکلی که هست تو pagination لینک هر 80 صفحه رو نشون میده و ظاهر صفحه بهم میخوره . در این روشی که گفتین میشه موارد زیر رو اعمال کرد؟
نمایش لینک صفحه اول - صفحه بعد - صفحه بعد+ - صفحه آخر
و اینکه صفحه ایی که در حال حاضر تو اون هستیم رو با رنگ مشخص کرد
این آموزش دقیقا به همین صورتی است که گفته اید، یعنی تنها چند صفحه قبل و بعد از صفحه فعلی در دسترس هستند، همچنین دکمه های صفحه آخر و اول و... نیز تعریف شده اند، سایر تغییرات سفارشی نیز از طریق استایل CSS امکانپذیر است!
یاسین
۱۱:۴۶ ۱۳۹۵/۰۵/۱۷
سلام. اگر بخواهیم نتایجی را که از چند جدول با ستون های متفاوت استخراج کردیم، پیج بندی کنیم راهی بجز union و ساخت فیلد null هست؟
با تشکر
منظورتان را از ساخت فیلد NULL دقیقا متوجه نشدیم! اما UNION یک امکان استاندارد در MySQL است که در صورت استفاده بهینه نیازی به استفاده از روش دیگر با هدف مشترک، احساس و توصیه نمی شود!
محسن
۲۲:۴۳ ۱۳۹۵/۰۳/۰۸
سلام. خیلی ممنون از آموزشتون. من ازین کد شما استفاده کردم. فقط میخام یطوری بشه که نتایج رو بصورت جدول نشون بده و قابلیت حذف کردن هم بهش اضافه بشه. من آموزش های دیگه شما رو دیدم هرچی سعی کردم نتونستم اینارو که گفتم خودم اضافه کنم. برام این کارو میکنید؟
یه کادر جستجو میشه بهش اضافه کرد؟
مواردی که مطرح کردید نیاز به کدنویسی سفارشی و زمانبر دارد که از چارچوب خدمات متداول سایت خارج است! لطفا با یک برنامه نویس وب موضوع را مطرح کنید.
more لطفا پیش از ارسال دیدگاه نکات زیر را مد نظر داشته باشید:
- به سوالات کلی، زمانبر، مبهم و مشکلاتی که تلاشی برای رفع آنها نکرده باشید پاسخ مختصر داده شده یا به بخش برنامه نویسی اختصاصی ارجاع داده می شوند.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین یا به صورت حساب موقت و آزمایشی قرار دهید تا امکان بررسی دقیق مشکل و خطایابی میسر باشد.
- تمام دیدگاه های ارسالی خوانده شده و برای هر کاربر مدت زمان لازم جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد در بازه زمانی کوتاه خودداری کنید.



 refresh
10 × 10
7 × 8
20 × 20
=