webew
Войти » Регистрация
 
PHP

Средства навигации по сайту: генерация с помощью PHP

25 декабря 2015, 15:31

Вниманию читателей предлагается небольшая библиотека функций для языка PHP, предназначенная, в основном, для создания интерфейсов навигации по спискам. Библиотека позволяет сделать необходимый PHP-код очень компактным.

Замена значений GET-параметров в адресах

Нередко бывает нужно получить URL, идентичный текущему, за исключением значения одного из GET-параметров.

Распространенный пример — номер страницы списка:

# Предположим, URL текущей страницы - http://site.ru/catalogue/?a=100&b=200&N=50

# Пусть за номер страницы отвечает параметр 'p'.
# Тогда чтобы получить URL для страницы № 2, нужен вот такой код:

$url = substitute_url_get_parameter('p', 2);

# Функция вернет адрес, начиная со слэша (без доменного имени):
# /catalogue/?a=100&b=200&N=50&p=2

Если в качестве значения GET-параметра функции передать NULL, то он будет полностью исключен из адреса:

# Предположим, мы на странице /catalogue/?a=100&b=200&N=50&p=2
$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

Если в адресе нужно заменить сразу несколько параметров, это можно сделать за один вызов функции:

# Для страницы /catalogue/?a=100&b=200&N=50&p=2&x=1

$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']). Если нужно использовать какой-то другой, его следует передать в качестве третьего аргумента:

$url = substitute_url_get_parameter('p', 2, $some_url);
# Вызов вида substitute_url_get_parameter('p', 2)
# равносилен substitute_url_get_parameter('p', 2, $_SERVER['REQUEST_URI'])

Есть специальный режим работы функции, который позволяет удалить из адреса все GET-параметры, кроме указанных, которым, при желании, установить другие значения или же оставить их в неизменном виде:

$url = substitute_url_get_parameter( ['-', 'N', 'x'=>3] );
# Для страницы 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():

$pages = nav_pages(
    'p', // номер страницы - в $_GET[p]
    20,  // сколько записей на одной странице  
    $total_rows // суммарное число записей в разбиваемом на странице списке
);

В случае текущего адреса /catalogue/?a=100&b=200&p=3 результат работы функции будет таким:

Array
(
    [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 присутствуют в случае, если первая или последняя страница не попали в общий список из-за ограничения на его длину. Это ограничение можно установить, передав функции дополнительный аргумент:

$pages = nav_pages(
    'p',
    20,  
    $total_rows,
    10 // перечень страниц должен состоять не более чем из 10-ти ссылок (не считая special)
);

Число записей на одной странице может, в свою очередь, регулироваться GET-параметром — можно указать функции использовать этот параметр и установить значение по умолчанию на случай, если он не задан:

$pages = nav_pages(
    'p',
    ['N', 20],   // число записей забираем из $_GET[N]  
    $total_rows, // если же $_GET[N] пуст или вовсе не задан — выводим по 20 штук
    10
);

Наконец, последним аргументом можно передать адрес, отличный от $_SERVER['REQUEST_URI'].

В меню навигации ссылку, соответствующую текущей странице, логично визуально выделить и при этом убрать у неё атрибут href1:

HTML-код такого меню можно получить из следующего шаблона (здесь и далее приводятся примеры для шаблонизатора websun):

<nav>
    Страницы:
    {?*special.first*} <a href="{*special.prev.first*}">в начало</a> {*special.first*?}
    {?*special.prev*} <a href="{*special.prev.url*}">предыдущая</a> {*special.prev*?}
    {%*list*}
        <a {?!*list:current*} href="{*list:url*}" {*list:current*?!} >{*list:num*}</a>
    {*list*%}
    {?*special.next*} <a href="{*special.next.url*}">следующая</a> {*special.next*?}
    {?*special.last*} <a href="{*special.prev.last*}">в конец</a> {*special.last*?}
</nav>

<style>
    /* для номера текущей страницы задаем свой стиль */
    nav a { font-weight: bold; }
   
    /* для остальных, которых отличаем по наличию атрибута href, стиль делаем другим */
    nav a[href] { font-weight: normal; }
</style>

Вместо номеров страниц можно указывать диапазон порядковых номеров самих записей:

В шаблоне для этого используются ключи min и max:

<nav>
    ...
    {%*list*}
        <a ...>{*list:min*}–{*list:max*}</a>
    {*list*%}
    ...
</nav>

Меню переключателей на основе GET-параметра

Встречаются ситуации, в которых нужно построить навигационное меню из однотипных ссылок, адреса которых отличаются только значением одного из GET-параметров2. При этом пункт меню, соответствующий текущей странице, должен визуально отличаться от остальных.

Обычно такие ситуации возникают при наличии нескольких режимов отображения у одного и того же содержимого. Предположим, некий список может быть представлен построчно (по умолчанию), мелкой сеткой или крупными плашками:

Для построения такого меню используется функция nav_switches(), которой требуется передать имя GET-параметра и перечень пунктов меню, каждый из которых определяется текстом ссылки и значением параметра3:

$cfg = [
    '' => 'построчно', // элемент с пустым ключом - по умолчанию
    'grid' => 'сетка',
    'plates' => 'плашки'
];

$menu = nav_switches('view', $cfg);

Например, для третьей страницы списка, представленного в виде сетки — адрес /catalogue/?p=3&view=grid — содержимое $menu таково:

Array
(
    [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-шаблон меню выглядит примерно так:

<menu>
{%**}<a {?!*:current*} href="{*:url*}" {*:current*?!}>{*:text*}</a>{**%}
</menu>

Другой пример переключения на основе GET-параметра — регулировка количества записей на странице.

// выводить по 10,20,50 и 100; по умолчанию - 20
$cfg = [ 10, '' => 20, 50, 100 ];

Здесь значение параметра — количество записей — служит сразу же и текстом ссылки (за исключением случая по умолчанию, когда значением является пустая строка).

При переключении количества записей логично отправлять пользователя на первую страницу списка, а не на текущую, поэтому GET-параметр, соответствующий номеру страницы, следует из всех адресов удалить. Для этого нужно указать его имя третьим аргументом:

$menu = nav_switches('N', $cfg, 'p');

Для страницы /catalogue/?p=3 $menu выглядит так:

Array
(
    [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+DESC4 — сортировка по убыванию цены

Обычно в меню сортировки каждому параметру соответствует по одной ссылке; та, что относится к выбранному в данный момент, выделяется визуально и при этом остается кликабельной, указывая на сортировку с противоположным направлением (это видно, если навести на нее указатель мыши). Например:

Для генерации данных подобного меню служит функция nav_sort(), вызов которой в данном случае будет выглядеть следующим образом:

$cfg = [
    'price' => 'по цене DESC',
    'name' => 'по названию',
    'date' => 'по дате DESC',
];

$menu = nav_sort('sort', $cfg, 'p');

// Третий аргумент — 'p' — указывает на имя GET-переменной,
// содержащей номер страницы, и необходим для того,
// чтобы каждая ссылка всегда указывала на первую страницу списка.

Содержимое $menu для страницы /catalogue/ выглядит так:

Array
(
    [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-шаблон меню выглядит примерно так:

<menu>
{%**}
    <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: " (возр.)"; }

В другом варианте организации меню отдельная ссылка соответствует каждому варианту направления сортировки, получается по две ссылки на каждый параметр:

Этому варианту соответствует такая конфигурация:

$cfg = [
    'price' => 'по {возрастанию|убыванию} цены DESC',
    'date' => 'по дате, сначала {старые|новые}'
];

Кроме того, понадобится немного другой шаблон:

<menu>
    {%**}
        <a
         {?*:current*} class="current" {*:current*?}
         {?*:url*} href="{*:url*}" {*:url*?}
        >
{*:text*}</a>
    {**%}
</menu>

Последним аргументом функции можно передать адрес страницы, если это не $_SERVER['REQUEST_URI'].

1. Отстутствие href сделает ссылку некликабельной.

2. Представление по умолчанию включается в случае отсутствия в адресе страницы GET-параметра, регулирующего представление.

3. Есть также полная форма записи, в двух вариантах:

// первый вариант
$cfg = [
    [ '', 'построчно' ],
    [ 'grid', 'сетка' ],
    [ 'plates', 'плашки' ]
];

// второй вариант
$cfg = [
    [ 'value' => '', 'title' => 'построчно' ],
    [ 'value' => 'grid', 'title' => 'сетка' ],
    [ 'value' => 'plates', 'title' => 'плашки' ]
];
Полную форму необходимо использовать, если значениями являются целые числа и при этом в качестве текстов используются не значения, а что-то другое. Например:
$cfg = [
    [ 1, 1000 ],
    [ 2, 2000 ],
    [ 3, 3000 ],
    [ 5, 'пять тысяч' ],
    [ 7, 'семь тысяч' ],
    [ 10, 'десять тысяч' ],
    [ 'value' => 20, 'title' => 'двадцать тысяч' ],
    [ 'value' => 30, 'title' => 'тридцать тысяч' ],
    [ 'value' => 40, 'title' => 40000 ],
    [ 'value' => 50, 'title' => 50000 ],
];

4. + — это URL-закодированный пробел. ASC — по возрастанию (от ascendant), DESC — по убыванию (от descendant), по аналогии с синтаксисом языка SQL.


© Все права на данную статью принадлежат порталу webew.ru. Перепечатка в интернет-изданиях разрешается только с указанием автора и прямой ссылки на оригинальную статью. Перепечатка в печатных изданиях допускается только с разрешения редакции.
Добавить комментарий

kolka

Спасибо.
Очень полезный набор!
28.12.2015, 16:59
Ответить

1234ru

Добавлена возможность удаления из адреса всех GET-параметров, кроме указанных.

Предыдущие изменения.

25.02.16. Инструмент переключения режимов сортировки: для случая, когда каждому направлению соответствует отдельная ссылка, изменена структура массива, добавлен уровень вложенности.
То, что не убивает нас, делает нас инвалидами.
23.03.2016, 13:25
Ответить

1234ru

Добавлена поддержка ассоциативного массива, содержащего значения GET-параметров для вставки в адрес:

substitute_url_get_parameter( [
    'a' => 5,
    'N' => 100,
    'p' => NULL,
    ...
] );

Предыдущие изменения.

23.03.16. Добавлена возможность удаления из адреса всех GET-параметров, кроме указанных.

25.02.16. Инструмент переключения режимов сортировки: для случая, когда каждому направлению соответствует отдельная ссылка, изменена структура массива, добавлен уровень вложенности.
То, что не убивает нас, делает нас инвалидами.
14.11.2016, 22:37
Ответить
© 2008—2017 webew.ru, связаться: x собака webew.ru
Сайт использует Flede и соответствует стандартам WAI-WCAG 1.0 на уровне A.
Rambler's Top100

Реклама: