Как да разделяме съдържанието на страници с PHP и MySQL

Как да разделяме съдържанието на страници с PHP и MySQL

В PHP, MySQL

За кого е предназначен този урок?

Този урок е предназначен за начинаещи програмисти, които искат да създадат най-опростена навигация в страницирането на своя динамичен сайт/документ. За да се справите с урока трябва да сте наясно със синтаксиса и семантиката на php и mysql.

Какво ще създадем?

Ще създадем страница, която точи информация от  база данни  и я разбива на страници. Подобен скрипт ще ви е полезен в практиката, защото когато създавате блог, страница, каталог или какъвто и да е документ, който има за цел да създава списъци от съдържанието на базата данни, ще ви се наложи да използвате странициране. Тук ще разгледаме заявката, която вади нужните ни записи от базата данни, заявката, която търси броя на всички записи, които ни трябват и логиката за изграждане на навигацията между страниците.

Да започваме…

Структура на базата ни данни

За да е по-лесно да следим урока, ще създадем таблица от базата данни, която да прилича на таблиците, които може да ни се наложи да създаваме в реалната ни практика. Таблицата ще се казва articles и ще има три колони:

id int(11)
article_name varchar(200)
article_content text

В тази таблица първата колона ни е идентификаторът id, който асоциира всяка статия с уникално за таблицата число, article_name и article_content са името на статията и текста й. За да запазим примера елементарен няма да разглеждаме колони, които пазят датата и часа на качване на статията. Практически погледнато, най-лесния начин да се подреждат записи хронологично е да се подреждат по стойността на техния id. Точно този начин ще използваме и тук. В реално приложение не разчитайте на id полето и използвайте подреждане по дата.

Създаване на страницата

Страницата ни ще се казва list.php. В нея ще поместим заявката и обработката на заявката към базата данни и ще печатаме резултата. По своята същност страницата ще бъде най-обикновен html документ, в който ще вмъкнем php кога, където ни трябва. така че отваряме си най-обикновен html:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Как да разделяме съдържанието на страници с PHP и MySQL</title>
</head>

<body>
</body>
</html>

Променлива за определяне на страницата

За да разбием записите от базата на страниците, трябва да имаме една променлива, която да предава на скрипта информация  на коя страница сме. Ще я наречем $page:

// Създаваме променливата $page
// Променливата показва на базата на коя страница е потребителя
//
if (isset($_GET['page']))
{
$page  = $_GET['page'];
}
else
{
$page = 1;
}
$start_from = ($page-1) * 6;
//
// $start_from ни трябва да заявката

С тези редове код проверяваме дали има подадена на скрипта $_GET променлива page. Ако има такава присвояваме стойността й на работната променлива $page. В противен случай създаваме $page със стойност 1. На следващия ред създаваме променливата $start_from, която получава стойността на страницата минус едно, делено на 6, където 6 е броя на записите на страница, които искаме да се появяват. Това е така, защото $start_from казва на базата от кой запис да почне, следователно ако сме на страница 5, значи първия ни запис трябва да е, ще искаме да почне да вади записи от края на страница 4, което е (5-1)*6

Заявката за записите

За да накараме базата данни да изважда записите на порции от по шест, трябва да използваме конструкцията LIMIT. Тя изисква два аргумента – първия казва на базата от кой запис да започне селекцията, а втория – колко записа да извади. След като изяснихме това, заявката към базата ни ще изглежда така:


// Заявката към базата с условието LIMIT
//
$sql = "SELECT * FROM articles ORDER BY id DESC LIMIT $start_from, 6";
//
// Заявката се подава на mysql_query()

Ако сме на първа страница, заявката ще ни върне записи от 0 до 5 (0 е стойността на $start_from и от нея, включително базата брои шест записа), ако сме на втора страница, ще ни върне от 6 до 11 и т.н. На този принцип заявката се променя според страниците така, че вече всичко зависи от алгоритъма за правене на връзките. Използваме подобен код, за да отпечатаме записите си:

// Скрипт за печатане на съдържанието на страница $page
//
$sql = "SELECT * FROM articles ORDER BY id DESC LIMIT $start_from, 6";
$db = db_connect();
if (!$db)
{
// при несвързване с базата изкарва съобщение и прекратява скрипта
echo 'Базата данни е временно недостъпна. Моля, опитайте по-късно.';
break;
}
// заявка към базата
$result = mysql_query($sql);
$num_results = mysql_num_rows($result);
for ($i=0; $i < $num_results; $i++)
{
// извеждаме резултатите
$row = mysql_fetch_array ($result);
echo '
<h1><a href="article.php?id='.$row['id'].'">'.$row['article_name'].'</a></h1>
<p>'.$row['article_content'].'</p>';
}
//
// Край на печата на съдържанието за страница $page

Заявка за всички записи

Схемата на работа от тук нататък е ясна – на страницата ни в момента седят отпечатани шест запис от базата. За да разберем върху колко страници ще бъдат отпечатани всички записи, трябва да намерим колко са те. Кодът за тази операция изглежда ето така:


// заявка за преброяване на всички записи
//
$rs_result = mysql_query("SELECT COUNT(`id`) FROM articles ");
//
// на $re_result ще се присвои ресурса, върнат от заявката

Намиране на нужния брой страници

Заявката използва конструкцията COUNT(‘id’), която връща резултат от преброяването на всички полета, имащи стойност в колоната id, т.е. – всички записи в таблицата. $row[0] е единствената стойност в масива, който mysql_result връща. $row[0] е броят на всички записи, отговарящи на условието ни (което в случая е просто да са в таблицата), затова го делим на 6 и закръгляме с помощта на функцията ceil().

Тя закръгля към по-голямата стойност, т.е. ако имаме 32 записа, то тогава ще имаме ceil(32/6) = ceil(5,3) или резултата ще е 6. Ако закръглим на 5 страници ще загубим два записа. Затова закръгляме на 6, като на последната страница получаваме 2 записа, вместо 6 (страницата е непълна). $total_records също може да ни е полезен, ако искаме да кажем на потребителя колко записа може да разгледа и на колко страници са те.

// Извличаме ресурса от $re_result
//
$row = mysql_fetch_row($rs_result);
$total_records = $row[0];
$total_pages = ceil($total_records / 6);
//
// Пристъпваме към if конструкцията

Странициране

Вече имаме променливата $page и $total_pages и можем вече да развиваме сценариите на страницирането. Има няколко сценария, които трябва да се разработят и предвидят, както и да се предвиди потребителското поведение:

  • Потребителя се намира на първа страница, но $total_pages също е равно на 1. При този вариант няма нужда се печата каквато и да навигация за стрелките;
  • Потребителя се намира на първа страница, а $total_pages е по-голям от едно. Тогава трябва да покажем на потребителя, че е на първа страница и да му дадем да избира само страници по-големи от 1;
  • Потребителя се намира на произволна страница, по-голяма от 1 и по-малка от $total_pages. Тогава трябва да му дадем информация на коя страница е (без линк) и възможност да се движи напред и назад;
  • Потребителят се намира на страница, равна на стойността на $total_pages. Тогава трябва да му дадем възможност да се движи само напред – към първа страница.

Всичко това може да се опише в един if, който ще изглежда ето така:

// За да оформим бутоните на страницата с CSS, най-лесно е да ги изпълним като списък
$pages = '<ul>';
// Намира се на първа страница и няма повече страници
if($page == 1 && $total_pages == 1)
{
$pages .= '';
}
// Намира се на първа от няколко страници
elseif($page == 1 && $total_pages > 1)
{
$pi     = $page+1;
// Печатаме страницата, на която се намира и й махаме линка
$pages .= '<li><a href="#">'.$page.'</a></li>';
$pages .= '<li><a href="link.php?page=2">2</a></li>';
$pages .= '<li><a href="link.php?page='.$total_pages.'">'.$total_pages.'</a></li>';
}

В този if правим един неактивен бутон за първа страница (защото потребителя ще е в нея) и след него ще се наредят активните бутони за втора и последна страница.

// Намира се на втора страница
elseif($page == 2 && $page < $total_pages)
{
$pi       = $page+1;
// Линк към първа страница
$pages .= '<li><a href="link.php?page=1">1</a></li>';
// Печатаме страницата, на която се намира и й махаме линка
$pages .= '<li><a href="#">'.$page.'</a></li>';
$pages .= '<li><a href="link.php?page='.$pi.'">'.$pi.'</a></li>';
// Линк към последна страница
$pages .= '<li><a href="link.php?page='.$total_pages.'">'.$total_pages.'</a></li>';
}

В този elseif показваме сценария за потребител на втора страница. Ако не направим подобен отделен сценарий и използваме структурата:

„първа страница | предходна страница | текуща страница | следваща страница | крайна страница“

за втора страница ще имаме: 1 | 1 | 2 | 3 | х , където х ни е $total_pages, което не можем да позволим.

// Намира се на предпоследна страница
elseif($page == $total_pages-2)
{
$mi       = $page-1;
// Линк към първа страница
$pages .= '<li><a href="link.php?page=1">1</a></li>';
$pages .= '<li><a href="link.php?page='.$mi.'">'.$mi.'</a></li>';
// Печатаме страницата, на която се намира и й махаме линка
$pages .= '<li><a href="#">'.$page.'</a></li>';
// Линк към последна страница
$pages .= '<li><a href="link.php?page='.$total_pages.'">'.$total_pages.'</a></li>';
}

В този elseif показваме сценария за потребител на предпоследна страница. Както казахме по-горе, ако не направим специален elseif за този случай, за предпоследна страница ще имаме: 1 | (x-1) | x | y | y , където х ни е $page, а y е $total_pages, което също не можем да позволим.

// Намира се на някоя от множество страници, по-голяма от 2
elseif ($page > 2 && $page < $total_pages)
{
$pi      = $page+1;
$mi     = $page-1;
// Линк към първа страница
$pages .= '<li><a href="link.php?page=1">1</a></li>';
$pages .= '<li><a href="link.php?page='.$mi.'">'.$mi.'</a></li>';
// Печатаме страницата, на която се намира и й махаме линка
$pages .= '<li><a href="#">'.$page.'</a></li>';
$pages .= '<li><a href="link.php?page='.$pi.'">'.$pi.'</a></li>';
// Линк към последна страница
$pages .= '<li><a href="link.php?page='.$total_pages.'">'.$total_pages.'</a></li>';
}

Тук вече можем да си позволим спокойствие, защото вече имаме проверките за втора и предпоследна страница, което означава, че ако се печата това, между първа/последна страница и текущата страница има поне 2 страници и няма да получим повторения на линковете.

// Намира се на последна страница
elseif($page == $total_pages)
{
$mi      = $page-1;
$mmi    = $page-2;
// Линк към първа страница
$pages .= '<li><a href="link.php?page=1">1</a></li>';
$pages .= '<li><a href="link.php?page='.$mmi.'">'.$mmi.'</a></li>';
$pages .= '<li><a href="link.php?page='.$mi.'">'.$mi.'</a></li>';
// Печатаме страницата, на която се намира и й махаме линка
$pages .= '<li><a href="#">'.$page.'</a></li>';
}
// Затваряме</ul>
тага
$pages .= '</ul>';

// Печатаме списъка с навигацията за страниците
echo $pages;

В примера съм показал печат на променливата $pages веднага след приключване на съставянето й, но това не винаги е задължително. Можем да съставим $pages и след това да я позиционираме ръчно в документа, където пожелаем.
Тъй като проверката за това в коя страница сме може да става независимо от печатането на съдържанието, можем да направим проверката в началото и да отпечатаме $pages както над (преди), така и под (след) шестте ни статии.

За Гергин Борисов

+359 877080887

Здравейте, аз съм Гергин Борисов, на 24 години от София и се занимавам с уеб и лого дизайн, предпечат и отскоро - с блога си. Занимавам се с дизайн от 2006та година насам, като преди това (от 2004та) работех в сферата на предпечата с баща ми, фотографът Александър Борисов.