Помогни ни да направим Uroci.net по - богат! Добави урок

Почти универсална техника за странициране на резултати от БД

PHP » PHP
lyubo   трудност:    видян: 13939

В този урок като ще видите как можете да си направите почти универсален страницатор.

Какво ново в тук показаната реализация?
Тук показаната реализация има следните по-важни черти:
1. Почти универсална е
2. Ниска степен на повтаряемост на кода при повторна нужда
3. Лесна адаптация към сложни БД заявки с възможност за управление на сортирането и групирането на резултати.
4. Приложимост върху повече от един списъка едновременно.
5. Грижата за генерирането на навигатора за разходка между страниците вече няма да ви тормози.

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

Описание на функцията
Функцията наречена pageQuery() се вика с три параметъра $qry, $pagenow, $perpage, като последния не е задължителен.
Първия параметър е асоциативен масив в който са зададени компонентите на заявката, както и някои други параметри управляващи процеса.
Втория и третия управляват текущата страница и броя резултати които да се показват на страница.

Идеята на функцията е да свърши цялата работа която винаги е еднаква при тази задача.
1. Първо се прави запитване към БД с което се уточнява колко редове общо отговарят на критерия по който търсим (ако изобщо търсим нещо)
2. На базата на този брой и променливата $perpage се изчисляват броя на страниците.
3. Конструира се LIMIT клауза
4. Конструира се навигатор от вида: <<Първа <Предишна [ 1 | 2 | 3 | 4 | 5 | 6 ] Следваща> Последна>>
5. Конструира се изходен масив.

Листинг на функцията (коментарите са важни)

//Някъде си имаме дефинирани константите:
define('ROWS_PREPAGE', 20);
define('DEFAULT_PAGER_NAME', 'pager');

function
pageQuery($qry, $pagenow=1, $perpage=0)
{

// В началото валидираме стойностите на входните променливи $pagenow и perpage
// Ако със стойностите нещо не е наред тогава им задаваме тези по подразбиране

if(!is_int($pagenow) || !isset($pagenow) || $pagenow < 1) $pagenow = 1;
if(!
is_int($perpage) || $perpage == 0) $perpage = ROWS_PREPAGE;

//Валидираме стойностите на масива съдържащ компонентите на заявката
if(!isset($qry['PAGER']) || $qry['PAGER'] == '') $qry['PAGER'] = DEFAULT_PAGER_NAME;

if(!isset(
$qry['WHERE']) || $qry['WHERE'] == '') $where = ' ';
else
$where = " WHERE $qry[WHERE]";

if(!isset(
$qry['ORDERBY']) || $qry['ORDERBY'] == '') $order_by = ' ';
else
$order_by = " ORDER BY $qry[ORDERBY]";

if(!isset(
$qry['GROUPBY']) || $qry['GROUPBY'] == '') $group_by = ' ';
else
$group_by = " GROUP BY $qry[GROUPBY]";

//Изпълняваме заявка към БД с цел да уточним колко резултати удовлетворяват WHERE клаузата
$query = "SELECT COUNT(*) AS CNT FROM $qry[FROM] $where $group_by";
$row_count = mysql_result(mysql_query($query, __FILE__.': '.__LINE__));

//И изчисляваме в колко страници се вместват резултатите които ни интересуват
$page_count = ceil($row_count/$perpage); //Важно е да използвате ceil() !

//Проверяваме дали номера на исканата страница не превишава $page_count
//Ако да -> променяме номера й на $page_count
if($pagenow > $page_count) $pagenow = (int)$page_count;

//Следващия фрагмент конструира LIMIT клаузата на SQL
//заявката, както и низ който ще представи информация за резултатите
if(is_int($pagenow) && $pagenow > 0){
$limit = (($pagenow-1)*$perpage).','.($perpage);
$str_results = (($pagenow-1)*$perpage+1).' до '.min($row_count, ($pagenow*$perpage));
}else {
$limit = '0,'.$perpage;
$str_results = '1 до '.min($row_count, ($pagenow*$perpage));
}
$limit = 'LIMIT '.$limit;

//Ако случайно няма повече от 1 страница -> Отказваме се от LIMIT клаузата
if($page_count == 0 || $page_count == 1) $limit = '';


/*Долния фрагмент се грижи за съзвадането на навигатора, чрез който потребителите могат да преминават
от страница в страница. Тук можете да поставите всякаква логика, която удовлетворява вашия графичен дизайн
В случая навигатора е стандартен от типа:

<<Първа <Предишна [ 1 | 2 | 3 | 4 | 5 | 6 ] Следваща> Последна>>
*/

//генериране на Първа и Предишна. Внимаваме да не накараме Предишна да сочи извън диапазона
$navi_str = "<a href="some_url.com?$qry[PAGER]=1"><<Първа </a>";
if(
$pagenow > 1) $navi_str .= "<a href="some_url.com?$qry[PAGER]=".$pagenow-1.""> <Предишна </a>";
else
$navi_str .= " <Предишна ";
//Номера на страниците. Текущата не е линк но е bold-ната
$separator = '';
for (
$i=1; $i<=$page_count; $i++){
if(
$i != $pagenow) $navi_str .= "<a href="some_url.com?$qry[PAGER]=$i">$separator $i </a>";
else
$navi_str .= "$separator <b>$i</b> ";
$separator = "|";
}
//генериране на Следваща и Последна. Отново внимаваме да не накараме Следваща да сочи извън диапазона
if($pagenow < $page_count) $navi_str .= "<a href="some_url.com?$qry[PAGER]=".$pagenow+1.""> Следваща> </a>";
else
$navi_str .= " Следваща> ";
$navi_str .= "<a href="some_url.com?$qry[PAGER]=$page_count"> Последна>></a>";

//ВАЖНО: В горния фрагмент, е изключително важно да се генерират правилно рефернциите на линковете!
//За целта се използва GET променлива с име $qry['PAGER'] която указва коя страничка искаме да разгледаме
//при щракването на този линк =>
//Целта името да може да бъде сменяно е, че може да ни се наложи да разлистваме повече от един списък в една HTML страница
// ОТНОВО: Внимавайте много с URL-тата. Във вашия конкретен случай ще е различно от тук!!!

//Вече сме подготвени да конструираме изходния масив
//в който можем да сложим каквато информация решим, че би ни заинтересувала.

//Като за начало да подготвим заявката с LIMIT каузата чрез която фактически ще извлечем резултатите от БД
$res['QUERY'] = "SELECT $qry[SELECT] FROM $qry[FROM] $where $group_by $order_by $limit";

//Всякъква друга информация
$res['PAGECOUNT'] = $page_count;
$res['PAGENOW'] = $pagenow;
$res['PERPAGE'] = $perpage;
$res['ROWCOUNT'] = $row_count; //Това показва общия брой резултати
$res['NAVIGATOR'] = $navi_str;
$res['RESULTS_INFO'] = "Резултати от $str_results; Страница $pagenow от $page_count";

//Ах колко банално - да върнем резултата! :)
return $res;
}


Използване
Сега да видим как можем да ползваме тази функция
Нека имаме някаква база данни с две таблици mastr_table и slave_table, като данните в двете се свързват по полето ID на master_table. Нека всички работи по канекцията към базата не ни интересуват. Сега за нас е важно следното:

//1. Като начало конструираме масив с компонентите на SQL заявката
$qry['SELECT'] = 'master_table.*, slave_table.*';
$qry['FROM'] = 'master_table, slave_table';
$qry['WHERE'] = 'master_table.ID>5 AND slave_table.MasterID = master_table.ID';
$qry['ORDERBY'] = 'master_table.ID DESC';
$qry['PAGER'] = 'articles_pager';
//2. Извикваме pageQuery();
$pgr_result = pageQuery($qry, (int)$HTTP_GET_VARS['articles_pager']);
//3. Взимаме си резултатите от Базата Данни
$result = mysql_query($pgr_result['QUERY']);
//4. И по най-стандартния начин обхождаме резултатите за да ги визуализираме
while ($row = mysql_fetch_array($result)){
//..като тук формираме HTML-а който ще визуализира самите резултати с данни
}

// Живи ли сте още? :)


Сега всеки път когато ви потрябва странициране просто е нужно да направите стъпките от 1 до 4 показани по-горе.
Вече можете да сте независими от случая и когато ви потрябва странициране го имате в рамките на 40 секунди.

Някои неказани неща
1. $qry масива има следната структура
$qry['SELECT'] - съдържа информация за SELECT клаузата. Задължително трябва да присъства
$qry['FROM'] - съдържа информация за FROM клаузата. Задължително трябва да присъства
$qry [ 'WHERE' ] - съдържа информация за WHERE клаузата. Незадължителна
$qry [ 'ORDERBY' ] - съдържа информация за ORDER BY клаузата.Незадължителна
$qry [ 'GROUPBY' ] - съдържа информация за GROUP BY клаузата.Незадължителна
$qry [ 'PAGER' ] - името на странициращата GET поменлива. Използва се за генериране на линковете в навигатора. Елемента не е задължиелен.

2. Обърнете внимание как е повикана pageQuery() в стъпка 3. и по специално на $HTTP_GET_VARS[ 'xxxxx' ];

Графики

Ето и някои приложения, като разбира се дискутираната функция, тук е значително усложнена:


уроци - pager.gif




Коментари (3)

d_badboy на 30.05 2007 в 15:30ч.
какво точно трябва да пиша тук: href="some_url.com?$qry[PAGER]=..."
lyubo на 10.06 2007 в 02:03ч.
На мястото на some_url.com трябва да сложиш домейна от който отговаря сайта (и разбира ако скрипта който използва кода по-горе не е index.php, трябва да го цитираш и него)

Примери:

Кода ти е сложен в index.php на домейн 192.168.0.60. Тогава там трябва да пише: http://192.168.0.60/index.php?$qry[PAGER]=xxxx (xxxx - в зависимост от конкретното място в кода)

Кода ти е сложен в some_script.php на домейн d_badboy.com Тогава там трябва да пише: http://d_badboy.com/some_script.php?$qry[PAGER]=xxxx (xxxx - в зависимост от конкретното място в кода)

Кода ти е сложен в www.d_badboy.com/scripts/some_script.php. Тогава там трябва да пише: http://www.d_badboy.com/scripts/some_script.php?$qry[PAGER]=xxxx (xxxx - в зависимост от конкретното място в кода)

Дано да е станало ясно.

Ако четеш обясненията - ето го и обяснението:

Значи, линкчето което се генерира, трябва да сочи към същия скриптов файл, където е разположена логиката за странициране на БД резултатите. Единствената разлика в няколкото линка е в номера на страницата който се изисква. Демек - всеки линк подава променлива с името на "страницатора", която му казва резултатите от коя страница да визуализира.
Така насочена връзката ще провокира скрипта да се изпълни в контекста на друга страница с резултати.

ПП. Навсякъде по-горе "страница" се отнася до страница с резултати от базата данни, а не към термина "интернет страница".
MJMP на 04.03 2008 в 17:48ч.
маи не само url-то ми епроблем обаче, дава ми грешка на този ред:
if($pagenow > 1) $navi_str .= " на тази, ако може малко помощ обаче...

Регистрирайте се, за да добавите коментар


Калдейта ЕООД - © 2003-2010. Всички права запазени.
Препоръчваме: IT Новини