Вот уже несколько дней ломаю голову над тривиальной задачей — автоматической генерацией ссылок для реализации универсальной постраничной навигации. Фишка в том, что движок работает без get-переменных, соответственно нужно это реализовать с REQUEST URI, номер страницы заносится в аргумент /page_*/ (вместо звездочки любая цифра).
Имеющиеся у меня варианты:
1. Беру REQUEST URI, провожу реврайт (например, превращаю /news/2 в /news/list/category_2/ по правилу '#^\/*news\/(\d+)\/?$#iu' => 'news/list/category_\\1'. Здесь news — экшен, list — эвент, а category_* — доп. аргумент) и парсинг, разбивая его на экшен, эвент и доп. параметры, ищу среди них page_*, заменяю его значение, нужное мне, снова собираю полученный массив в URI-строку и отдаю в шаблонизатор. Если page_* среди параметров нет — добавляю ее.
— Работает, но как-то очень длинно, разборки-сборки массива.
2. Опять же, беру REQUEST URI и прямо в строке, по регулярному выражению заменяю page_* на нужное значение и отдаю в шаблонизатор. Вроде бы ок, но если значения page_ изначально нет в URI — оно и не заменится, ссылка получится бесполезной. Поэтому придется вначале проверять, есть ли вхождения подстроки page_ в строку URI и дальше уже проводить вышеуказанные действия или просто дописывать в конец page_*.
— Еще длиннее получилось.
Подскажите, есть ли какой-нибудь вариант покороче и попроще, как это реализовать? По правилам реврайта, page_* может отсутствовать вовсе или находиться в конце URI.
Спустя 1 час, 22 минуты, 37 секунд (3.09.2012 - 20:21) Guest написал(а):
куккисы
Спустя 28 минут, 37 секунд (3.09.2012 - 20:50) AlmazDelDiablo написал(а):
Кукисы? Эм... Увы, не подходит, так как при такой реализации невозможно будет давать прямую ссылку на нужную страницу.
UPD
Сделал вот так:
Шаблон выглядит вот так:
UPD
Сделал вот так:
/**
* Создает ссылки для постраничной навигации.
* Возвращает шаблон для встраивания.
*
* @param $iCountPages — кол-во страниц
* @param $iCurrentPage — выбранная страница.
* @param $sUri — URI, на основе которого строятся ссылки.
* @return string
*/
public function getPagination( $iCountPages, $iCurrentPage, $sUri ) {
$sUri = preg_replace( '#/*page_\d+/*#iu', '', $sUri );
$aLinks = array();
$aLinks[1] = $sUri .'/page_1';
($iCurrentPage > 4 ? $aLinks[2] = '...' : null);
$iMin = (($iCurrentPage-3) < 1 ? 2 : ($iCurrentPage-2));
$iMax = (($iCurrentPage+3) > $iCountPages ? ($iCountPages-1) : ($iCurrentPage+2));
for( $i = $iMin; $i <= $iMax; $i++ ) {
$aLinks[$i] = $sUri .'/page_'. $i;
}
(($iCountPages-4) >= $iCurrentPage ? $aLinks[$iCountPages-1] = '...' : null);
$aLinks[$iCountPages] = $sUri .'/page_'. $iCountPages;
$this->assign( 'iPage', $iCurrentPage );
$this->assign( 'aPagination', $aLinks );
ob_start();
$this->display( 'pagination' );
$sTpl = ob_get_clean();
return $sTpl;
}
Шаблон выглядит вот так:
<div class="pagination">
Страницы:
{foreach $aPagination as $iIndex => $sLink}
{if $iIndex == $iPage}
{$iIndex}
{else if $sLink == '...'}
{$sLink}
{else}
<a href="{$sLink}">{$iIndex}</a>
{/if}
{/foreach}
</div>
Спустя 12 часов, 36 секунд (4.09.2012 - 08:50) SlavaFr написал(а):
шаблон страшно смотреть,
я представляю сколько усилий стоило написать на php то, что в пхп уже давно имеется и от шаблона не чем не отличается.
я представляю сколько усилий стоило написать на php то, что в пхп уже давно имеется и от шаблона не чем не отличается.
Цитата (AlmazDelDiablo @ 3.09.2012 - 16:58) |
... дней ломаю голову над тривиальной задачей — автоматической генерацией ссылок для реализации универсальной постраничной навигации. |
в каком месте универсальность реализована? Я собственно вижу только конкретный случай где в урл будет стоять статический техт /page_{$pageNr} и где обсалютно не проверяется действительное наличие страниц.
К сожалению универсальность выглядет на много абстрактней и требует для каждого конкретного случая дополнительной доработки (имплементации абстрактных методов) и понимания.
Спустя 1 час, 48 минут, 25 секунд (4.09.2012 - 10:39) AlmazDelDiablo написал(а):
На счет шаблона — это старый-добрый Smarty. Конечно, можно сделать <?php foreach() ... ?>, но не красиво это.
Действительное наличие страниц проверяется в модуле вывода новостей, где эти новости забираются из базы, считается кол-во страниц и т.д. Так что, если ввести в адрес page_1000000, когда у нас только 2 страницы — будет 404-я ошибка.
На счет большей абстрактности — я, увы, не понимаю, зачем еще сильнее усложнять такую вещь, как пагинация. Подскажите логику поведения полноценной системы постраничной навигации, может, мне и впрямь стоит о ней задуматься?
Действительное наличие страниц проверяется в модуле вывода новостей, где эти новости забираются из базы, считается кол-во страниц и т.д. Так что, если ввести в адрес page_1000000, когда у нас только 2 страницы — будет 404-я ошибка.
На счет большей абстрактности — я, увы, не понимаю, зачем еще сильнее усложнять такую вещь, как пагинация. Подскажите логику поведения полноценной системы постраничной навигации, может, мне и впрямь стоит о ней задуматься?
Спустя 1 час, 33 секунды (4.09.2012 - 11:39) SlavaFr написал(а):
Цитата (AlmazDelDiablo @ 4.09.2012 - 08:39) |
я, увы, не понимаю, зачем еще сильнее усложнять такую вещь, как пагинация |
Усложнять не надо,
просто если мы делаем УНИВЕРСАЛЬНОЕ решение, то должны реализовать все так, чтоб каждый мог систему под себя подстроить. То есть не кто ничего против готового решения не имеет, но должна быть открыта возможность подстроить систему под собственные потребности. Для этого система должна быть так фукнционально раздроблена, чтоб люди могли посредством переделывания не всего кода, а только отдельных изолированых частей, добится того, чтоб система соответствовала его потребностям.
к примеру
$aLinks[1] = $sUri .'/page_1';
могла бы выглядеть как
$aLinкs[1] = $this->buildLinkUrl($i);
и те которые бы хотели по своему организовать построение урл не переписывали бы весь класс или весь метод getPagination, а только метод buildLinkUrl .
Или например те кому не нравится Смарти могли бы использовать использовать свои методы для образования OUTPUT при чем без применения ob_start().
Проблема:
Когда все будет зделано то появляется к сожалению солжная и более объемная структура, которую начинающие программисты лучше перепишут из за непонимания заново, чем подстроят имеющуюся под себя :). Это основная проблема и делама создания УНИВЕРСАЛЬНЫХ решений.
:)
Спустя 34 минуты, 50 секунд (4.09.2012 - 12:14) AlmazDelDiablo написал(а):
Хм... Задумку понял, буду обдумывать полную реализацию.
Спасибо за идею :)
Спасибо за идею :)
Спустя 2 часа, 54 минуты, 32 секунды (4.09.2012 - 15:09) bodja написал(а):
Держи свой универсальный пагинатор и вставляй куда хочеш.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" >
<title>Paginator</title>
<meta name="keywords" content="" >
<meta name="description" content="" >
<style>
</style>
</head>
<body>
<div id="pagination"></div>
</body>
<script type="text/javascript">
function paginator(all, cnt, link) {
var p = document.getElementById('pagination');
var f = false;
for (var i = 0; i < all; i++) {
if ((i > 2 && (cnt - 1) > i) || ((cnt + 1) < i && (all - 3) > i)) {
if (!f) {
f = true;
var el = document.createElement('span');
el.style.cssText = 'background:#fff;font:bold 13px Tahoma;color:#000;margin-left:3px;padding:3px;';
el.innerHTML = '...';
p.appendChild(el);
}
} else {
f = false;
var el = document.createElement('span');
el.style.cssText = 'background:#bbb;font:bold 13px Tahoma;color:#fff;margin-left:3px;padding:3px;cursor:pointer;';
el.innerHTML = i + 1;
el.onclick = function (o, i, link) {
return function () {
document.location.href = link + '/page_' + (i + 1);
}
}
(this, i, link);
p.appendChild(el);
}
}
}
paginator(62, 14, 'http://domain.net');
</script>
</html>
_____________
Блог | VK | GitHub | Twitch