Как сделать пагинацию php
Перейти к содержимому

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

  • автор:

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

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

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

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

INSERT INTO `articles` (`author_id`, `name`, `text`) VALUES (1, 'Название статьи 1', 'Текст статьи 1'), (1, 'Название статьи 2', 'Текст статьи 2'), (1, 'Название статьи 3', 'Текст статьи 3'), (1, 'Название статьи 4', 'Текст статьи 4'), (1, 'Название статьи 5', 'Текст статьи 5'), (1, 'Название статьи 6', 'Текст статьи 6'), (1, 'Название статьи 7', 'Текст статьи 7'), (1, 'Название статьи 8', 'Текст статьи 8'), (1, 'Название статьи 9', 'Текст статьи 9'), (1, 'Название статьи 10', 'Текст статьи 10'), (1, 'Название статьи 11', 'Текст статьи 11'), (1, 'Название статьи 12', 'Текст статьи 12'), (1, 'Название статьи 13', 'Текст статьи 13'), (1, 'Название статьи 14', 'Текст статьи 14'), (1, 'Название статьи 15', 'Текст статьи 15'), (1, 'Название статьи 16', 'Текст статьи 16'), (1, 'Название статьи 17', 'Текст статьи 17'), (1, 'Название статьи 18', 'Текст статьи 18'), (1, 'Название статьи 19', 'Текст статьи 19'), (1, 'Название статьи 20', 'Текст статьи 20');

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

  • Привет, мир!
  • Развернуть строку
  • Чётные числа
  • Числа Фибоначчи
SELECT * FROM articles ORDER BY id DESC;

Все записи без пагинации

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

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

  • Курс HTML для начинающих
  • Курс PHP для начинающих
  • Курс MySQL для начинающих
  • Курс ООП в PHP
SELECT * FROM articles ORDER BY id DESC LIMIT 10 OFFSET 5;

OFFSET и LIMIT

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

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

SELECT * FROM articles ORDER BY id DESC LIMIT 5 OFFSET 0;

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

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

SELECT * FROM articles ORDER BY id DESC LIMIT 5 OFFSET 5;

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

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

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

SELECT * FROM articles ORDER BY id DESC LIMIT 5 OFFSET 10;

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

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

SELECT * FROM articles ORDER BY id DESC LIMIT k OFFSET (n-1)*k;

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

SELECT COUNT(*) FROM articles;

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

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

public static function getPagesCount(int $itemsPerPage): int < $db = Db::getInstance(); $result = $db->query('SELECT COUNT(*) AS cnt FROM ' . static::getTableName() . ';'); return ceil($result[0]->cnt / $itemsPerPage); >

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

public function main() < $articles = Article::findAll(); $this->view->renderHtml('main/main.php', [ 'articles' => $articles, 'pagesCount' => Article::getPagesCount(5), ]); >

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

  

getId() ?>">getName() ?>

getText() ?>


">

Номера страничек

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

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

/** * @return static[] */ public static function getPage(int $pageNum, int $itemsPerPage): array < $db = Db::getInstance(); return $db->query( sprintf( 'SELECT * FROM `%s` ORDER BY id DESC LIMIT %d OFFSET %d;', static::getTableName(), $itemsPerPage, ($pageNum - 1) * $itemsPerPage ), [], static::class ); >

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

public function page(int $pageNum) < $this->view->renderHtml('main/main.php', [ 'articles' => Article::getPage($pageNum, 5), 'pagesCount' => Article::getPagesCount(5), ]); >

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

public function main() < $this->page(1); >

Первая страница

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

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

'~^(\d+)$~' => [\MyProject\Controllers\MainController::class, 'page'],

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

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

public function page(int $pageNum) < $this->view->renderHtml('main/main.php', [ 'articles' => Article::getPage($pageNum, 5), 'pagesCount' => Article::getPagesCount(5), 'currentPageNum' => $pageNum, ]); >

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

  

getId() ?>">getName() ?>

getText() ?>


">

Последняя страница

Результат:

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

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

Пагинация на PHP

простая пагинация на php

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

Подключение БД:

Первым делом как обычно нужно подключить базу данных, для этого видите этот код.

$server = ‘localhost’ ; // Имя или адрес сервера
$user = ‘root’ ; // Имя пользователя БД
$password = » ; // Пароль пользователя
$db = ‘test’ ; // Название БД
$db = mysqli_connect ( $server , $user , $password , $db ) ; // Подключение
// Check connection
// Проверка на подключение
// Если проверку не прошло, то выводится надпись ошибки и заканчивается работа скрипта
echo «Не удается подключиться к серверу базы данных!» ;

В этом коде первым делом у нас идут переменные для настройки при подключение БД, потом уже подключаемся, после пишем условии для проверки подключения базы данных, если его нет, то выводим надпись «Не удается подключиться к серверу базы данных!», и запрещаем дальше работать скрипту.

Создание пагинации на PHP:

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

// Поверка, есть ли GET запрос
if ( isset ( $_GET [ ‘pageno’ ] ) ) < // Если да то переменной $pageno присваиваем его $pageno = $_GET [ 'pageno' ] ; > else < // Иначе // Присваиваем $pageno один // Назначаем количество данных на одной странице $size_page = 5 ; // Вычисляем с какого объекта начать выводить $offset = ( $pageno - 1 ) * $size_page ;

Тут не чего особо сложного нет, в начале проверяем, если у нас GET запрос pageno , который отвечает за номер страницы, если есть, то присваиваем этот номер переменной $pageno , иначе ей даём значение один.

Также создаём переменную $size_page в которой хранится сколько данных нужно выводить на одной страницы, и $offset , которая вычисляет с какого элемента нужно начать выводить.

Теперь нужно вычислить сколько всего мы имеем страниц.

// SQL запрос для получения количества элементов
$count_sql = «SELECT COUNT(*) FROM `user`» ;
// Отправляем запрос для получения количества элементов
$result = mysqli_query ( $db , $count_sql ) ;
// Получаем результат
$total_rows = mysqli_fetch_array ( $result ) [ 0 ] ;
// Вычисляем количество страниц
$total_pages = ceil ( $total_rows / $size_page ) ;

Тут сперва мы создаём строку с SQL запросом, которое получает количество элементов в БД, потом отправляем этот запрос в базу данных, и получаем число количества , потом вычисляем сколько всего страниц, делением количеств элементов, на число данных на одной странице.

Делаем вывод данных.

// Создаём SQL запрос для получения данных
$sql = «SELECT * FROM `user` LIMIT $offset, $size_page» ;
// Отправляем SQL запрос
$res_data = mysqli_query ( $db , $sql ) ;
// Цикл для вывода строк
while ( $row = mysqli_fetch_array ( $res_data ) ) < // Выводим логин пользователя echo $row [ 'login' ] . '
‘ ;
// Закрываем соединение с БД
mysqli_close ( $db ) ;

Здесь мы создаём SQL запрос и в нём после слова LIMIT назначаем от какого элемента брать и сколько, потом делаем запрос к БД, и вывод данные которые получили, закрываем соединение с MySQL.

Последние нужно добавить кнопки пагинации, для этого вот что пишем.

< a href = "else < echo " ? pageno = ".($pageno - 1); >?>» > Prev < / a >
< li class = "= $total_pages) < echo 'disabled'; >?>» >
< a href = "= $total_pages) < echo '#'; >else < echo " ? pageno = ".($pageno + 1); >?>» > Next < / a >

То есть тут добавляем пару кнопок и всё, также стоит сказать, что я использовал bootstrap, для более красивого отображения, его думаю сами сможете подключить, так мы сделали скрипт простой пагинации на PHP, вот результат.

скрипт простой пагинации на php

Если мы нажмём на кнопку «Next», то у нас переключится, вот это всё что нужно знать.

Вывод:

В этой статье вы прочитали как делается простая пагинация на PHP, также вы можете скачать скрипт, что больше понять как это всё работает.

Ещё стоит сказать, что я брал код с этого сайта, по ссылке.

Как разбить данные на страницы с помощью PHP

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

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

Хотя мой уровень в отношении баз данных не таков, как был раньше, сейчас он значительно богаче,
со времени моего первого знакомства с PHP и MySQL, меня пленила
мысль делать вещи более простыми и легкими в использовании.

Как разработчик я постоянно сталкиваюсь с одной проблемой: принятие большого количества информации и попытка легко усвоить ее. Является ли это список клиентов крупной компании или личный mp3-каталог, вынужденность сидеть и смотреть на строку над строкой, строку над строкой разных данных может быть весьма скучным занятием
и даже более — вы можете разочароваться. Что может сделать хороший разработчик? Разбить на страницы!

1. Разбивка на страницы

Разбиение на страницы — это по существу процесс принятия набора результатов и распределение
их по страницам, чтоб их было легче читать.

example 1example 1 example 1

Ещё раньше я размышлял, если бы у меня было 500 строчек информации, которую нужно отобразить, это было бы
не только головной болью для того, кто попытается все это прочитать, но и большинство браузеров
потратили бы целую вечность (т.е. более чем пять секунд) на отображение этой информации.

Чтобы решить эту проблему я мог бы написать разные инструкции SQL, чтобы вытащить фрагменты данных, и если бы у меня
было хорошее настроение, я бы даже сделал пару кнопок, «далее» и «предыдущая».
Через некоторое время, мне нужно было внести этот код в очень похожий проект и настроить
его, чтобы подогнать под старый вариант. Быстро. И как каждый хороший разработчик знает, лень рождает изобретательность
или что-то в этом роде. Поэтому, однажды, я сел и решил придумать простой,
гибкий и легкий в использовании класс PHP, который автоматически бы делал грязную работу
вместо меня.

Несколько слов обо мне и классах PHP. Я не волшебник в сфере объектно-ориентированного программирования. На самом деле, я практически
никогда не использую подобные вещи. Но после прочтения некоторых примеров ООП и учебных материалов, а также
простых примеров проб и ошибок, я решил сделать решительный поворот, и знаете, что?
Он идеально работает для разбивки на страницы. Код, который я здесь использую, написан в PHP 4, но
он работает и в PHP 5.

2. База данных

Вам нужно любить MySQL. Не хочу обидеть другие системы баз данных, но
для меня, все что мне нужно — это MySQL. Одной из прекрасных особенностью MySQL является то, что они дают вам
некоторые бесплатные примеры баз данных, с которыми вы можете поиграться: http://dev.mysql.com/doc/#sampledb.

В моем случае я буду использовать всемирную базу данных (архив ~ 90 k), которая содержит
свыше 4000 записей, с которыми можно поработать, но красота PHP-скрипта, который мы будем создавать, в том,
что его можна использовать для любой базы данных. Теперь, думаю, мы все можем согласиться, что если мы решили
не разбивать наши результаты, в итоге мы получим очень длинный и громоздкий
список результатов, как примерно показано ниже:

example 2

Потому давайте пойдем дальше, разбивая наши данные в легко обрабатываемые байты, как показано ниже:

example 3example 3 example 3

Красиво, не так ли? После того, как вы ввели клас разбивки на страницы в ваш код, вы можете
быстро и просто превратить огромный набор данных в страницы, по которым можно легко перемещаться
с помощью всего нескольких строк кода. Это на самом деле так.

3. Пагинатор

Данный пример будет состоять с двух скриптов, многоразового класса paginator и файла index, который будет выводить элементы таблицы и элементы управления.

Paginator.class.php

Класс рaginator будет иметь только два метода и конструктор, мы будем строить их постепенно, объясняя каждый шаг по мере того, как мы движемся вперед.

Как сделать ЧПУ-пагинацию на «Битрикс»?

При использовании пагинации (в просторечии постранички) на «Битрикс» адреса красотой не блещут. Сначала отображается адрес ЧПУ, а в конце его древний костыль PAGEN_. Разве это дело? Нет, конечно. И вот как исправить положение:

1. Организуем буферизацию вывода system.pagenavigation

Обратите внимание, что для вызова анонимной функции потребуется интерпретатор PHP версии не ниже 5.3.

 > $strNavQueryString = ($arResult['NavQueryString'] != '' ? $arResult['NavQueryString'].'&' : ''); $strNavQueryStringFull = ($arResult['NavQueryString'] != '' ? '?'.$arResult['NavQueryString'] : ''); ob_start(); ?> ******** YOUR TPL ******* $newUrl = preg_replace('#(pagen[\d]+/)#is', '', $newUrl); parse_str(htmlspecialcharsback($arUrl['query']), $arQuery); foreach ($arQuery as $k => $v) < if (in_array($k, array('SECTION_CODE'))) < unset($arQuery[$k]); >elseif (substr($k, 0, 5)=='PAGEN') < $newUrl .= 'pagen'.intval($v).'/'; unset($arQuery[$k]); >> $buildQuery = http_build_query($arQuery, '', '&'); if (strlen($buildQuery)) < $newUrl .= '?'.$buildQuery; >> return 'href="'.$newUrl.'"'; >, $paging); ob_end_clean(); echo $paging;

2. Модифицируем .htaccess

В файл .htaccess надо добавить строчку:

RewriteRule ^(.*)/pagen([\d]+)/ /$1/?PAGEN_1=$2 [L,QSA]

3. Для «Битрикс» версий ниже 15.5 используем обработчик

AddEventHandler('main', 'OnPageStart', array('CMainhandlers', 'OnPageStartHandler')); class CMainhandlers < public static function OnPageStartHandler() < $newUri = preg_replace('#(pagen[\d]+/)#is', '', $_SERVER['REQUEST_URI']); if (!CHTTP::isPathTraversalUri($newUri)) < $_SERVER['REQUEST_URI'] = $newUri; $GLOBALS['APPLICATION']->reinitPath(); > > >

4. Для «Битрикс» версий 15.5 и высших

Обработчик не используем. Если ранее использовали, то удаляем.

Создаем файл /bitrix/pagen.php с кодом:

$uri = trim($uri); return preg_match(«#(?:/|2f|^|\\\\|5c)(?:(?:%0*(25)*2e)|\\.)(?:/|%0*(25)*2f|\\\\|%0*(25)*5c|$)#i», $uri) ? true : false; > $newUri = preg_replace(‘#(index[\d]+\.html)#is’, », $_SERVER[‘REQUEST_URI’]); if (!__isPathTraversalUri($newUri))

И в файл .htaccess добавьте строчку:

php_value auto_prepend_file "***/bitrix/pagen.php"

Заменив звездочки на ваш док.рут. Обязательно редактируйте файл .htaccess только по FTH/SSH доступам.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *