Как сделать пагинацию php

от admin

How to Create Ajax Pagination and Filters With PHP

Taking what we learnt in a previous post, “How To Create Pagination With PHP“, we’ll revisit the pagination tutorial and throw in some extra filters. Thanks to Ajax and JQuery, we’ll do all of this without having to reload the page.

Prerequisites

  • A basic understanding of PHP.
  • A very basic understanding of JQuery and how Ajax works.
  • JQuery installed/included.

Before we begin, check out a working version of this tutorial here. You can also download the code from GitHub.

For this tutorial, I’ve created five files, however, only the first two are required:

  • products-array.php:The PHP file with the products array. This file is only for the purpose of this tutorial. Typically, you’d be requesting this data from your database, which will most likely be presented in an associative array like this.
  • index.php:The main page template.
  • products.php:The products template. This must be kept separate. We’ll use Ajax to request this file and dynamically load the content into the appropriate container. I’ve included the pagination template in this file using PHP’s require() function.
  • pagination.php:The pagination template. This doesn’t have to be separate. If you prefer, include this in the products template file.
  • pagination.js: The Javascript file to take care of the Ajax. This is a small amount of code and doesn’t need to be in it’s own file. You can include this in your website or apps primary .js file.

To keep this tutorial simple, I won’t discuss the layout. I’m also going to exclude the typical HTML (ie. html, body, header, footer, etc) from the code.

The Products Array That We’ll Filter With Ajax

This is an multi-dimensional array of products which we can pretend either comes from the database, or from an API call. When we call $products, it will be this array by default, however we’ll override this later when we filter and paginate. This file is products-array.php.

The Main PHP File

This file contains the filter form and the div that will hold the products. The code below is included in index.php, except I’ve excluded the basic HTML.

The Products File Template

The file will serve two purposes: to create a template for the individual products and to do the logic that will dictate which products should be shown, based on the filters and pagination. This file is products.php.

Looking at the above code, we can see a few things happening here. First we include the products.

Then, we check if there are any queries set and assign them to a variable. I’m using a ternary if statement and if there aren’t any $_GET parameters, those variables will be empty.

Next, we set our default limit, offset and current page. Your default offset should always be 0 to make sure that, when no queries are set, the products show from the first one. Your current page, by default, should be 1.

The if statement checks if a page-number query is set and if it is, $current_page will then become that value instead of 1, while $offset will calculate what the new offset should be.

Now we have to check which products are being requested. In the code below, we check if either the category filter ($cat_filter aka $_GET[‘cats’]) or the search filter ($search_filter aka $_GET[‘search’]) have values. If they aren’t empty, we’ll proceed with the filters. In the foreach loop, when the filter matches the query, it will be pushed into the $filtered_products array.

Filter Products Based on User Query With Conditional Statements

The first part of the conditional ( if ( !empty($cat_filter) && !empty($search_filter) ) ) checks if both category and search have values and will look for matches that include both terms. For the text search it will check if either the title contains the query or if the SKU is the search term.

If the category and search query don’t both have values, the second part of the conditional ( else if(!empty($cat_filter) && $product[‘category’] == $cat_filter) ) will take effect. This checks only for product categories.

The last part of the conditional statement will use the search query ( else if(!empty($search_filter) && ( strpos($product[‘title’], $search_filter) !== false || $product[‘sku’] == $search_filter) ) ). This is similar to the first condition, except it excludes the categories and will only take effect if $cat_filter is empty.

Finally, when the loop completes we will redefine $products by making it a copy of $filtered_products. If $products is an empty array, we let the user know that no products match the query.

Now, one of three outcomes will be true:

  • Either there aren’t any queries in place, in which case, none of the previous code in the if statement will run and our $products variable will still be the original one in products_array.php,
  • Filters are in place and products were found, redefining $productswith the values of $filtered_products,
  • Or filters are in place and no products were found, redefining $productswith the empty $filtered_products array.

Now we will use PHP’s array_slice() to limit and offset the $products array so we can add pagination. This sliced array is stored in $paged_products which you can think of as a segment of the $products array that will be shown when pagination is in effect. $limit and $offset were defined earlier.

The following code is self-explanatory and just defines some variables we’ll use to make things a bit easier to read. In the last part, we check our total products compared to the amount currently shown. Logically, we only need pagination if the total is more than what’s currently on the page.

If pagination is required, we call the pagination template.

The Pagination Template

The pagination template also includes some required logic along with the HTML.

In the following code, we use PHP’s http_build_query() function to generate a query we’ll send through ajax when we page. This will ensure we keep the filters, since with Ajax, we can’t grab them from the URL. We’re going to use this as an HTML data attribute (data-query) we can access in JQuery along with the additional data-page-number attribute .

For an explanation of the for loop and pagination, please see “How To Create Pagination With PHP“, which has a thorough explanation of how we can determine which page we’re on to build a working pagination template.

JQuery and Ajax Pagination

Finally, in our Javascript we add the following code:

In the above code, the first function will be in charge of determining what happens when we click any of the pagination links. The page_number variable grabs the data we set in the data-page-number attribute while current_query uses the value set in data-query we built with the http_build_query() PHP function.

This will send a request to products.php, appending the current filter query (if there is one set) and additionally send the requested page number (ie. offset). The server will then send back the data from the PHP file with newly queries items.

JQuery’s html() function will load that HTML into the div with the id of all-products.

The second function is similar, but is only responsible for filtering, not pagination. It serialises all the inputs from the form with JQuery’s serialize() helper function when the user submits the form. The products.php file then does what it needs to do and sends back the data based on the request.

As you can see, creating a paged list of products or posts with filters and search features without the need to reload is not difficult at all. In this tutorial we used built in functions for both PHP and JQuery, and didn’t even need to write our own functions to make it work!

Постраничная навигация на PHP

Часто при разработке и выводе контента появляется необходимость использования постраничной навигации. Кто-то скорее всего использует готовые решения от своего фреймворка. Кто-то, возможно, не заморачивается и лупит страницы просто циклом. У кого-то есть свои наработки в этом направлении. Вот я как раз и хочу поделиться своим решением данной задачи.

Читать:
Callable python что это

Существует множество вариаций расположения и отображения кнопок, лично я пришел к следующему решению, которое по моему мнению наиболее наглядно и удобно. Подходит как для 5 страниц так и для 5000.

Пример HTML кода

Не буду ходить вокруг да около, сразу приложу пример сформированного скриптом html кода:

Логика построения

По настройкам параметров я остановлюсь чуть позже после приведения кода, сейчас опишу логику формирования самих номеров.

С кнопками «Назад» и «Вперед» думаю все понятно, к тому же их можно просто отключить, поэтому на них не буду заострять внимания.

Первый и последний номер страницы отображается всегда, своего рода кнопки «В начало» и «В конец».

Середина формируется уже по простому алгоритму. Отображается просматриваемая страница и по N страниц по бокам. На примере отображается по N=3 страницы. В принципе все просто и понятно, но особая хитрость используется при приближении к краям. Опишу на примерах:

Страница 1-3 (где 3 = N)

Отображаются первые N*2 страниц и последняя.

Отображается первая и дальше сформированная строка от 4-3=1 до 4+3=7. Первая страница зарезервирована поэтому формируются номера от 2 до 7.

Пожалуй во всех навигациях что я видел (включая хабр) строка была бы сформирована с пропуском, т.е. 1… 3 4 5 6 7 8 9… 17
Но ведь это не логично, отображать многоточие вместо одного числа. При построении второго многоточия выполняется аналогичная проверка.

Середина уже стандартна.

Формирование окончания аналогично началу

Страница 12

Редиректы

Помимо этого из особенностей хочу выделить еще 2 момента, это проверка существования страницы и редирект на «правильный» адрес. Т.е. к примеру, тут же на хабре первая страница может быть доступна сразу по 2м адресам:
habrahabr.ru/sandbox/page1
habrahabr.ru/sandbox

Скрипт не дает зайти на адрес page/1/ и выполняет редирект на «чистый» адрес
Так же если указан слишком большой номер страницы будет выполнен редирект на последнюю существующую. К примеру были удалены материалы или изменено количество записей на страницу. Не могу правда однозначно сказать полезно ли это будет с точки зрения СЕО, но для пользователей мне кажется так будет удобнее.

PHP код и его использование

Для наглядности, приведу пример построения навигации песочницы:
habrahabr.ru/sandbox/page12

Или же если номер страницы прописан внутри URL:
example.com/some_url/1.html — первая страница
example.com/some_url/1-page2.html — вторая страница

$limit — количество записей на страницу
$count_all — общее количество записей
$page_num — номер страницы на которой находится пользователь

На этом, пожалуй, всё. Буду рад любой конструктивной критике.

PS. Огромное спасибо всем отписавшимся, особенно тем кто ругает (и правильно делает).
Обещаю со всем ознакомиться, принять во внимание и исправиться.

Простая пагинация на PHP/Javascript. Создаем постраничную навигацию

Разрабатывая любой проект часто приходиться сталкиваться с необходимостью создания постраничной навигации или как еще называют — пагинация. Будь-то список статей, пользователей или любые другие выборки с базы данных, где большое количество записей требуют лимитированного вывода. Такой вывод можно реализовать двумя способами:

1. Выгружать все данные и показывать пользователю только часть.
2. Выгружать только часть данных, которые непосредственно показывать.

Каждый из способов имеет свои плюсы и минусы, очевидно, если записей в базе очень много, то выгружая все, мы очень сильно нагружаем компьютер пользователя. Просто представьте, что при открытии страницы у вас подгружается 100.000 записей, с другой стороны, если выгрузка имеет только 100 элементов, то такой способ будет работать быстрее, так как не нужно постоянно обращаться к серверу.

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

1. Функция pagePrint(), печатает ссылку на заданую страницу

$page — номер страницы;
$title — анкор ссылки (например, «1», «2», «10», «следующая»);
$show — показывать ссылку или текст, используется, чтобы вывести текущую страницу, или же неактивные ссылки «назад», «вперед»;
$active_class — класс CSS для активной страницы.

2. Начальный конфиг
3. Пример выборки данных из базы

Для выборки используется LIMIT, где старт вычисляется по формуле (page-1)*limit, то есть для первой страницы start = 0.

4. Подсчет кол-ва страниц и проверка основных условий.

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

Пример, всего записей 31, на странице публикуем по 10, таким образом по формуле получается 3.1 страница, при округлении round(3.1) = 3, что неправильно, так как теряется одна запись. Поэтому используется функция ceil(), ceil(3.1) = 4.

5. Выводим на экран:

Вот и все, алгоритм разобран, ниже представлен код для вывода пагинации на Javascript:

Остались вопросы — задаем в комментариях, также делимся своими наработками, если знаете как «красивее» реализовать пагинацию.

Делаем пагинацию на PHP

Зачастую в тестовых заданиях на джунов присутствует пункт о реализации пагинации в какой-нибудь системе. И мне довольно часто прилетают просьбы показать как это делается, так как зачастую это задание ставит в тупик начинающих разработчиков. Что-ж, давайте разбираться.

Делать пагинацию я хочу предложить на базе написанного нами в курсе ООП в PHP движка для блога. Готовый проект можно взять по ссылке. Накатите дамп базы и настройте веб-сервер так, чтобы корневой директорией для домена myproject.loc была папка www.

Теперь давайте добавим побольше статей в базу, чтобы было по чему пагинацию делать.

Посмотрим на имеющиеся у нас статьи. Отсортируем их в обратном порядке.

Теперь, если вы еще не в курсе, нужно познакомиться с двумя конструкциями языка SQL: LIMIT и OFFSET. Они позволяют получить только часть строк из тех, что были получены запросом. LIMIT задаёт лимит записей, OFFSET задает количество строк, которые нужно пропустить.

Например, мы хотим пропустить первые 5 строк, и вывести следующие 10 строк:

OFFSET и LIMIT

Как видим, у нас пропустились первые 5 строк с id: 22,21,20,19,18, которые присутствовали в результате запроса без LIMIT и OFFSET. Также мы видим, что строк у нас здесь 10.

Как нетрудно догадаться, для реализации пагинации нам можно воспользоваться этими конструкциями. Если мы хотим выводить на каждой странице нашего блога по 5 записей, то для получения записей на первой странице стоит использовать запрос:

Первые 5 записей

Для второй страницы запрос будет следующим:

Следующие 5 записей

То есть здесь мы пропустили первые 5 записей и вывели следующие 5.

Аналогично строим запрос для третьей страницы:

И так далее, пока записи не закончатся.

Получаем формулу для получения запроса, которые выводит записи на n-ой странице блога, где k-число записей на одной странице:

Чтобы понять, сколько у нас будет страниц, нам нужно число записей разделить на число записей, выводимых на одной странице. Полученное число округляем в большую сторону. К примеру, если у нас 22 записи, и на одной странице выводим 5, то число страниц будет 22/5 = 4,4. Округляем в большую сторону и получаем 5. На первых четырех страницах у нас будет по 5 записей, а на последней будет 2 записи.
Получить общее число записей можно с помощью запроса:

Число записей

Осталось всё это дело закодить. Начнём с самого простого – выведем ссылки на странички со статьями.
В классе ActiveRecordEntity добавляем метод для получения количества страниц. Метод будет принимать на вход количество записей на одной странице.

В MainController вызовем этот метод и передадим в шаблон число страниц.

Добавим в шаблоне внизу странички номера страниц.

Обратите внимание: при формировании ссылки на страницу мы проверяем, является ли страничка первой, и если это так, то формируем ссылку на главную страницу, иначе формируем ссылку вида: /n, где n – номер страницы.
Посмотрим на результат:
Номера страничек

Теперь давайте напишем метод для получения записей на n-ой страничке. Для этого в классе ActiveRecordEntity добавим метод getPage(), принимающий на вход количество записей на одной странице и номер страницы.

Добавим в MainController экшен для странички.

Переписываем экшен main.

Проверяем главную страницу:
Первая страница

Добавляем роут для страничек с номерами.

Всё. Пагинация готова. Можно переходить по страничкам. Так выглядит пятая страница.

Из улучшений можно сделать текущий номер страницы не ссылкой, а просто текстом. Для этого передадим номер текущей странички в шаблон.

В шаблоне будем сравнивать текущий номер страницы с тем, который в текущей итерации.

Результат:
Последняя страница

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

Похожие статьи