Средства навигации по сайту: генерация с помощью PHP
Вниманию читателей предлагается небольшая библиотека функций для языка PHP, предназначенная, в основном, для создания интерфейсов навигации по спискам. Библиотека позволяет сделать необходимый PHP-код очень компактным.
Замена значений GET-параметров в адресах
Нередко бывает нужно получить URL, идентичный текущему, за исключением значения одного из GET-параметров.
Распространенный пример — номер страницы списка:
# Пусть за номер страницы отвечает параметр 'p'.
# Тогда чтобы получить URL для страницы № 2, нужен вот такой код:
$url = substitute_url_get_parameter('p', 2);
# Функция вернет адрес, начиная со слэша (без доменного имени):
# /catalogue/?a=100&b=200&N=50&p=2
Если в качестве значения GET-параметра функции передать NULL, то он будет полностью исключен из адреса:
$url = substitute_url_get_parameter('p', ''); // вернет /catalogue/?a=100&b=200&N=50&p
$url = substitute_url_get_parameter('p', NULL); // вернет /catalogue/?a=100&b=200&N=50
Если в адресе нужно заменить сразу несколько параметров, это можно сделать за один вызов функции:
$url = substitute_url_get_parameter( [ 'N' => 100, 'p' => NULL ] );
# даст /catalogue/?a=100&b=200&N=100&x=1
# Можно указывать единое значение для всех параметров (это удобно, если их нужно удалить)
$url = substitute_url_get_parameter(['N', 'p'], ''); # даст /catalogue/?a=100&b=200&N&p&x=1
$url = substitute_url_get_parameter(['N', 'p'], NULL); # даст /catalogue/?a=100&b=200&x=1
По умолчанию функция использует адрес текущей страницы ($_SERVER['REQUEST_URI']). Если нужно использовать какой-то другой, его следует передать в качестве третьего аргумента:
# Вызов вида substitute_url_get_parameter('p', 2)
# равносилен substitute_url_get_parameter('p', 2, $_SERVER['REQUEST_URI'])
Есть специальный режим работы функции, который позволяет удалить из адреса все GET-параметры, кроме указанных, которым, при желании, установить другие значения или же оставить их в неизменном виде:
# Для страницы http://site.ru/catalogue/?a=100&b=200&N=50&x=1
# даст http://site.ru/catalogue/?N=50&x=3
Как видно из примера, для работы в этом режиме первым аргументом функции нужно передать массив, первым элементом которого является строка '-', а последующими — те переменные, которые следует оставить в адресе.
Соответственно, вызов вида substitute_url_get_parameter( ['-'] ) позволяет получить адрес без GET-параметров.
Разбиение списка на страницы
Типичная задача при работе со списком — получить перечень ссылок, соответствующих разным страницам этого списка. Номеру страницы при этом соответствует некоторый GET-параметр; в случае первой страницы он не задан и не должен присутствовать в ссылке на нее. Все остальные части адреса от страницы к странице должны сохраняться неизменными.
Для решения такой задачи служит функция nav_pages():
'p', // номер страницы - в $_GET[p]
20, // сколько записей на одной странице
$total_rows // суммарное число записей в разбиваемом на странице списке
);
В случае текущего адреса /catalogue/?a=100&b=200&p=3 результат работы функции будет таким:
(
[list] => Array
(
[1] => Array
(
[url] => /catalogue/?a=100&b=200
[num] => 1
[min] => 1
[max] => 20
)
[2] => Array
(
[url] => /catalogue/?a=100&b=200&p=2
[num] => 2
[min] => 21
[max] => 40
)
[3] => Array
(
[url] => /catalogue/?a=100&b=200&p=3
[num] => 3
[min] => 41
[max] => 60
[current] => 1
)
[4] => Array
(
[url] => /catalogue/?a=100&b=200&p=4
[num] => 4
[min] => 61
[max] => 80
)
...
)
[special] => Array
(
[current] => Array
(
[url] => /catalogue/?a=100&b=200&p=3
[num] => 3
[min] => 41
[max] => 60
)
[prev] => Array
(
[url] => /catalogue/?a=100&b=200&p=2
[num] => 2
[min] => 21
[max] => 40
)
[next] => Array
(
[url] => /catalogue/?a=100&b=200&p=4
[num] => 4
[min] => 61
[max] => 80
)
)
)
Ссылки prev и next присутствуют, если текущей не является первая или последняя страница соответственно. Ссылки first и last присутствуют в случае, если первая или последняя страница не попали в общий список из-за ограничения на его длину1. Это ограничение можно установить, передав функции дополнительный аргумент:
'p',
20,
$total_rows,
10 // перечень страниц должен состоять не более чем из 10-ти ссылок (не считая special)
);
Число записей на одной странице может, в свою очередь, регулироваться GET-параметром — можно указать функции использовать этот параметр и установить значение по умолчанию на случай, если он не задан:
'p',
['N', 20], // число записей забираем из $_GET[N]
$total_rows, // если же $_GET[N] пуст или вовсе не задан — выводим по 20 штук
10
);
Наконец, последним аргументом можно передать адрес, отличный от $_SERVER['REQUEST_URI'].
В меню навигации ссылку, соответствующую текущей странице, логично визуально выделить и при этом убрать у неё атрибут href2:
HTML-код такого меню можно получить из следующего шаблона (здесь и далее приводятся примеры для шаблонизатора websun):
Страницы:
{?*special.first*} <a href="{*special.first.url*}">в начало</a> {?}
{?*special.prev*} <a href="{*special.prev.url*}">предыдущая</a> {?}
{%*list*}
<a {?!*list:current*} href="{*list:url*}" {?} >{*list:num*}</a>
{%}
{?*special.next*} <a href="{*special.next.url*}">следующая</a> {?}
{?*special.last*} <a href="{*special.last.url*}">в конец</a> {?}
</nav>
<style>
/* для текущей страницы и остальных устанавливаем разные стили; отличаем их по наличию атрибута href */
nav a[href] { font-weight: normal; }
nav a:not([href]) { font-weight: bold; }
</style>
Вместо номеров страниц можно указывать диапазон порядковых номеров самих записей:
В шаблоне для этого используются ключи min и max:
...
{%*list*}
<a ...>{*list:min*}–{*list:max*}</a>
{*list*%}
...
</nav>
Меню переключателей на основе GET-параметра
Встречаются ситуации, в которых нужно построить навигационное меню из однотипных ссылок, адреса которых отличаются только значением одного из GET-параметров3. При этом пункт меню, соответствующий текущей странице, должен визуально отличаться от остальных.
Обычно такие ситуации возникают при наличии нескольких режимов отображения у одного и того же содержимого. Предположим, некий список может быть представлен построчно (по умолчанию), мелкой сеткой или крупными плашками:
Для построения такого меню используется функция nav_switches(), которой требуется передать имя GET-параметра и перечень пунктов меню, каждый из которых определяется текстом ссылки и значением параметра4:
'' => 'построчно', // элемент с пустым ключом - по умолчанию
'grid' => 'сетка',
'plates' => 'плашки'
];
$menu = nav_switches('view', $cfg);
Например, для третьей страницы списка, представленного в виде сетки — адрес /catalogue/?p=3&view=grid — содержимое $menu таково:
(
[0] => Array
(
[value] =>
[text] => построчно
[current] =>
[url] => /catalogue/?p=3
)
[1] => Array
(
[value] => grid
[text] => сетка
[current] => 1
[url] => /catalogue/?p=3&view=grid
)
[2] => Array
(
[value] => plates
[text] => плашки
[current] =>
[url] => /catalogue/?p=3&view=plates
)
)
Следует отметить, что все GET-параметры, кроме view, сохраняют свои значения в адресах ссылок меню. При этом в ссылке на вид построчно view отсутствует, поскольку этот вид выбран в качестве представления списка по умолчанию.
HTML-шаблон меню выглядит примерно так:
{%**}<a {?!*:current*} href="{*:url*}" {*:current*?!}>{*:text*}</a>{**%}
</menu>
Другой пример переключения на основе GET-параметра — регулировка количества записей на странице.
$cfg = [ 10, '' => 20, 50, 100 ];
Здесь значение параметра — количество записей — служит сразу же и текстом ссылки (за исключением случая по умолчанию, когда значением является пустая строка).
При переключении количества записей логично отправлять пользователя на первую страницу списка, а не на текущую, поэтому GET-параметр, соответствующий номеру страницы, следует из всех адресов удалить. Для этого нужно указать его имя третьим аргументом:
Для страницы /catalogue/?p=3 $menu выглядит так:
(
[0] => Array
(
[value] => 10
[text] => 10
[current] =>
[url] => /catalogue/?N=10
)
[1] => Array
(
[value] =>
[text] => 20
[current] => 1
[url] => /catalogue/
)
[2] => Array
(
[value] => 50
[text] => 50
[current] =>
[url] => /catalogue/?N=50
)
[3] => Array
(
[value] => 100
[text] => 100
[current] =>
[url] => /catalogue/?N=100
)
)
Последним аргументом можно передать адрес страницы, для которой строится меню, если это не $_SERVER['REQUEST_URI'].
Переключение режимов сортировки
Режим сортировки определяется не только параметром, по которому она осуществляется, но также и направлением (возрастание или убывание).
Один из способов управления сортировкой через адрес страницы состоит в использовании GET-переменной, значение которой содержит указание на режим сортировки в формате параметр направление. Например:
- ...&sort=price — сортировка по возрастанию цены
- ...&sort=price+DESC5 — сортировка по убыванию цены
Обычно в меню сортировки каждому параметру соответствует по одной ссылке; та, что относится к выбранному в данный момент, выделяется визуально и при этом остается кликабельной, указывая на сортировку с противоположным направлением (это видно, если навести на нее указатель мыши). Например:
Для генерации данных подобного меню служит функция nav_sort(), вызов которой в данном случае будет выглядеть следующим образом:
'price' => 'по цене DESC',
'name' => 'по названию',
'date' => 'по дате DESC',
];
$menu = nav_sort('sort', $cfg, 'p');
// Третий аргумент — 'p' — указывает на имя GET-переменной,
// содержащей номер страницы, и необходим для того,
// чтобы каждая ссылка всегда указывала на первую страницу списка.
Содержимое $menu для страницы /catalogue/ выглядит так:
(
[0] => Array
(
[is_current] => 1
[direction] => DESC
[url] => /t-ajax.php?sort=price
[text] => по цене
)
[1] => Array
(
[is_current] =>
[direction] => ASC
[url] => /t-ajax.php?sort=name
[text] => по названию
)
[2] => Array
(
[is_current] =>
[direction] => DESC
[url] => /t-ajax.php?sort=date+DESC
[text] => по дате
)
)
HTML-шаблон меню выглядит примерно так:
{%**}
<a
class="{?*:current*}current{*:current*?} {*:direction*}"
href="{*:url*}"
>{*:text*}</a>
{**%}
</menu>
Каждая из ссылок в таком случае будет иметь класс ASC или DESC, а соответствующая текущему режиму сортировки — еще и класс current. Это позволит эффективно управлять их внешним видом с помощью CSS:
a.current { font-weight: bold; }
/* В зависимости от направления дописываем к тексту ссылки фрагмент "(возр.|убыв.)". */
a.ASC:after { content: " (возр.)"; }
a.DESC:after { content: " (убыв.)"; }
/* У выделенных ссылок ситуация сложнее:
при наведении мыши они должны показывать то направление,
которое станет действовать, если на ссылку нажать,
то есть обратное текущему. */
a.current.ASC:hover:after { content: " (убыв.)"; }
a.current.DESC:hover:after { content: " (возр.)"; }
В другом варианте организации меню отдельная ссылка соответствует каждому варианту направления сортировки, получается по две ссылки на каждый параметр:
Этому варианту соответствует такая конфигурация:
'price' => 'по {возрастанию|убыванию} цены DESC',
'date' => 'по дате, сначала {старые|новые}'
];
Кроме того, понадобится немного другой шаблон:
{%**}
<a
{?*:current*} class="current" {*:current*?}
{?*:url*} href="{*:url*}" {*:url*?}
>{*:text*}</a>
{**%}
</menu>
Последним аргументом функции можно передать адрес страницы, если это не $_SERVER['REQUEST_URI'].
forward соответствует странице, следующей за последней из основного списка.
Если «уже далеко» до первой страницы - в special появляется ссылка backward; соответствует странице, предшествующей самой первой из основного списка.
$cfg = [
[ '', 'построчно' ],
[ 'grid', 'сетка' ],
[ 'plates', 'плашки' ]
];
// второй вариант
$cfg = [
[ 'value' => '', 'title' => 'построчно' ],
[ 'value' => 'grid', 'title' => 'сетка' ],
[ 'value' => 'plates', 'title' => 'плашки' ]
];
[ 1, 1000 ],
[ 2, 2000 ],
[ 3, 3000 ],
[ 5, 'пять тысяч' ],
[ 7, 'семь тысяч' ],
[ 10, 'десять тысяч' ],
[ 'value' => 20, 'title' => 'двадцать тысяч' ],
[ 'value' => 30, 'title' => 'тридцать тысяч' ],
[ 'value' => 40, 'title' => 40000 ],
[ 'value' => 50, 'title' => 50000 ],
];
© Все права на данную статью принадлежат порталу webew.ru. Перепечатка в интернет-изданиях разрешается только с указанием автора и прямой ссылки на оригинальную статью. Перепечатка в печатных изданиях допускается только с разрешения редакции.