Как на MVC и PHP сделать вывод новостей из БД с использованием пагинации


X

Как на MVC и PHP сделать вывод новостей из БД с использованием пагинации

В прошлой статье мы рассматривали, как добавить новости в базу данных. Теперь мы будем выводить эти новости постранично с использование класса Pagination.

Для начала прописываем путь к обработчику страницы.

'news' => 'news/newsPage',

 

Теперь создадим сам обработчик в файле NewsController.php. Он по умолчанию получает значение page равное 1, это нужно для того, чтобы пагинация начиналась с первой страницы.

В NewsList  с помощью функции getNewsLimit получаем сами новости из таблицы базы данных. В total при помощи функции getCountNews запишется общее количество новостей.

Затем создаем Pagination, он имеет следующий синтаксис: Pagination(общее количество новостей, номер страницы, максимальное количество новостей на странице, ‘символ который будет подставлен в адресную строку перед номером страницы’)

В итоге у нас получится вот такой метод:

public function actionNewsPage($page = 1)
{
    $NewsList = News::getNewsLimit($page);
    $total = News::getCountNews();
    $pagination = new Pagination($total, $page, News::SHOW_BY_DEFAULT, '');
    require_once(ROOT . '/views/site/news.php');
    return true;
}

 

Теперь опишем используемые функции и константу:

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

const SHOW_BY_DEFAULT = 3;

 

Функция getNewsLimit. По факту это просто запрос в базу данных с последующей записью результат в массив, но есть одно отличие. Мы берем записи из таблицы базы данных со смещением, относительно текущей страницы пагинации и максимального количества записей.

Допустим, мы переходим на третью страницу пагинации, значение переменной page становится равным трем, так как отчет записей с базы данных мы начинаем с нуля. Максимальное количество элементов на странице равно трем.  Мы отнимаем от page единицу и умножаем на максимальное количество новостей. Таким образом, мы получаем выражение (3-1)*3, оно равно числу шесть, то есть мы будем брать записи, из БД начиная с шестой по счету.

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

В результате выполнения SQL запроса мы получим limit записей, начиная от offset элемента.

public static function getNewsLimit($page=1){
    $limit = self::SHOW_BY_DEFAULT;
    $offset = ($page - 1) * self::SHOW_BY_DEFAULT;
    $db = Db::getConnection();
    $sql = 'SELECT * FROM news ORDER BY id DESC LIMIT :limit OFFSET :offset ';
    $result = $db->prepare($sql);
    $result->bindParam(':limit', $limit, PDO::PARAM_INT);
    $result->bindParam(':offset', $offset, PDO::PARAM_INT);
    $result->execute();
    $i = 0;
    $news = array();
    while ($row = $result->fetch()) {
        $news[$i]['id'] = $row['id'];
        $news[$i]['title'] = $row['title'];
        $news[$i]['date'] = $row['date'];
        $news[$i]['img_url'] = $row['img_url'];
        $news[$i]['url'] = $row['url'];
        $i++;
    }
    return $news;
}

 

Функция getCountNews. Простой SQL запрос, который считает количество элементов в таблице базы данных по id:

public static function getCountNews()
{
    $db = Db::getConnection();
    $sql = 'SELECT count(id) AS count FROM news';
    $result = $db->prepare($sql);
    $result->execute();
    $row = $result->fetch();
    return $row['count'];
}

 

Теперь пришло время создать страницу, на которой мы будем выводить элементы. У меня она выглядит вот так:

С помощью цикла foreach выводим записи на страницу. Массив NewsList мы получаем из обработчика который находится в NewsController. Эта страница имеет следующий листинг:

<html>
<head>
    <title>Новости</title>
</head>
<body>
    <h1>НОВОСТИ</h1>
    <table>
        <tr style="background:#ececec;">
            <td style="width:5%;">№</td>
            <td>Изображение</td>
            <td>Заголовок</td>
            <td>Url</td>
            <td>Дата</td>
        </tr>
        <?php foreach ($NewsList as $news): ?>
            <tr>
                <td style="width:5%;"><?php echo $news['id']; ?></td>
                <td style="width:150px;">
                    <img src="/img/<?php echo $news['img_url']; ?>" style="width:150px;">
                </td>
                <td><?php echo $news['title'];?></td>
                <td><?php echo $news['url'];?></td>
                <td>
                    <?php
                        $exp = explode('-', $news['date']);
                        $date = $exp[2].'.'.$exp[1].'.'.$exp[0];
                        echo "<i>".$date."</i>";
                    ?>
                </td>
            </tr>
        <?php endforeach; ?>
    </table>
    <br>

 

Тут мы будем выводить нумерацию страниц. Нумерация будет выводиться в виде маркированного списка li. Нам нужно чтобы нумерация выводилась в строчку и без маркировки. Для этого мы будем использовать CSS.

Задаем стиль списку li находящемуся в классе pagination. С помощью list-style-type мы убираем маркеры, с помощью float: left мы поставим все элементы в строчку. margin-right задаст расстояние между номерами в три пикселя. Далее внутри блока, с помощью PHP конструкции выведем pagination, который мы создали в контроллере:

    <style>
        .pagination li {
            list-style-type: none;
            float: left;
            margin-right: 3px;
        }
    </style>
    <div class="pagination" style="margin-left:20%;"><?php echo $pagination->get(); ?></div>
</body>
</html>

 

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

Сам класс Pagination.php. Его нужно будет создать в папке components:

<?php
class Pagination
{
    /**
     * @var Ссылок навигации на страницу
     */
    private $max = 10;
    /**
     * @var Ключ для GET, в который пишется номер страницы
     */
    private $index = 'page';
    /**
     * @var Текущая страница
     */
    private $current_page;
    /**
     * @var Общее количество записей
     */
    private $total;
    /**
     * @var Записей на страницу
     */
    private $limit;
    /**
     * Запуск необходимых данных для навигации
     * @param type $total <p>Общее количество записей</p>
     * @param type $currentPage <p>Номер текущей страницы</p>
     * @param type $limit <p>Количество записей на страницу</p>
     * @param type $index <p>Ключ для url</p>
     */
    public function __construct($total, $currentPage, $limit, $index)
    {
        # Устанавливаем общее количество записей
        $this->total = $total;
        # Устанавливаем количество записей на страницу
        $this->limit = $limit;
        # Устанавливаем ключ в url
        $this->index = $index;
        # Устанавливаем количество страниц
        $this->amount = $this->amount();
        # Устанавливаем номер текущей страницы
        $this->setCurrentPage($currentPage);
    }
    /**
     *  Для вывода ссылок
     * @return HTML-код со ссылками навигации
     */
    public function get()
    {
        # Для записи ссылок
        $links = null;
        # Получаем ограничения для цикла
        $limits = $this->limits();
        $html = '<ul class="pagination">';
        # Генерируем ссылки
        for ($page = $limits[0]; $page <= $limits[1]; $page++) {
            # Если текущая это текущая страница, ссылки нет и добавляется класс active
            if ($page == $this->current_page) {
                $links .= '<li class="active"><a href="">' . $page . '</a></li>';
            } else {
                # Иначе генерируем ссылку
                $links .= $this->generateHtml($page);
            }
        }
        # Если ссылки создались
        if (!is_null($links)) {
            # Если текущая страница не первая
            if ($this->current_page > 1)
            # Создаём ссылку "На первую"
                $links = $this->generateHtml(1, '&lt;') . $links;
            # Если текущая страница не первая
            if ($this->current_page < $this->amount)
            # Создаём ссылку "На последнюю"
                $links .= $this->generateHtml($this->amount, '&gt;');
        }
        $html .= $links . '</ul>';
        # Возвращаем html
        return $html;
    }
    /**
     * Для генерации HTML-кода ссылки

     * @param integer $page - номер страницы

     * @return
     */
    private function generateHtml($page, $text = null)
    {
        # Если текст ссылки не указан
        if (!$text)
        # Указываем, что текст - цифра страницы
            $text = $page
        $currentURI = rtrim($_SERVER['REQUEST_URI'], '/') . '/';
        //$currentURI = preg_replace('~/page-[0-9]+~', '', $currentURI);
        $currentURI = preg_replace('~/[0-9]+~', '', $currentURI);
        # Формируем HTML код ссылки и возвращаем
        return
                '<li><a href="' . $currentURI . $this->index . $page . '">' . $text . '</a></li>';
    }
    /**
     *  Для получения, откуда стартовать

     * @return массив с началом и концом отсчёта

     */
    private function limits()
    {
        # Вычисляем ссылки слева (чтобы активная ссылка была посередине)
        $left = $this->current_page - round($this->max / 2);
        # Вычисляем начало отсчёта
        $start = $left > 0 ? $left : 1;
        # Если впереди есть как минимум $this->max страниц
        if ($start + $this->max <= $this->amount) {
        # Назначаем конец цикла вперёд на $this->max страниц или просто на минимум
            $end = $start > 1 ? $start + $this->max : $this->max;
        } else {
            # Конец - общее количество страниц
            $end = $this->amount;
            # Начало - минус $this->max от конца
            $start = $this->amount - $this->max > 0 ? $this->amount - $this->max : 1;
        }
        # Возвращаем
        return
                array($start, $end);
    }
    /**
     * Для установки текущей страницыу

     * @return
     */
    private function setCurrentPage($currentPage)
    {
        # Получаем номер страницы
        $this->current_page = $currentPage;
        # Если текущая страница больше нуля
        if ($this->current_page > 0) {
            # Если текущая страница меньше общего количества страниц
            if ($this->current_page > $this->amount)
            # Устанавливаем страницу на последнюю
                $this->current_page = $this->amount;
        } else
        # Устанавливаем страницу на первую
            $this->current_page = 1;
    }
    /**
     * Для получения общего числа страниц

     * @return число страниц

     */
    private function amount()
    {
        # Делим и возвращаем
        return ceil($this->total / $this->limit);
    }
}

Смотрите также дополнительные статьи про MVC

Grai Просмотров сегодня +6 27 июня 2017 команда сайта
Ещё пока нет комментариев, будь первым!
Оставить комментарий
   🔔 Отдохните не много, может Вам будет интересно прочитать статьи пользователей нашего сайта.

Тег abbr - это аббревиатура

Как на MVC с помощью PHP и MySQL создать счетчик просмотров страниц

Основные запросы SQL работа с базой данных PHP

Как на AJAX передать переменные в PHP с выводом результата в блок с проверкой условий без перезагрузки страницы

Тег area - это область ссылки

Как создать свою CMS или фреймворк на MVC. Часть Первая

Тег b - это полужирный шрифт

Тег datalist - это список возможных вариантов

Тег acronym - это акроним

Как на MVC при помощи PHP создать регистрацию с хешированием пароля

Недостатки раскрутки групп Вконтакте специальными сервисами

Как проверить радио кнопку checkbox без перезагрузки страницы ajax php

Создание сайтов и мобильных приложений от 5 500 руб. Любой сложности!
Реклама Собственный фреймворк. Большие и сложные проекты. ТОП 100 разработчиков РФ.
Создание сайтов от 5 500 руб.
Мобильные приложения от 50 000 руб.
irogex.ru
Наши проекты Инстаграм от 6 500 руб.
Конструкторы Ugears купить в Иркутске от 690 руб. с Доставкой!
Реклама UGEARS это путешествие в удивительную атмосферу гармонии природы и совершенства конструкторской мысли
Конструктор Навигатор дат - 690 руб.
Конструктор Комбайн - 2990 руб.
ugears-irk.ru
Оплата и Доставка Контакты
Стоматология в Улан-Удэ | ДентаВита | Шок цены от 100 руб!
Реклама От всей нашей семьи хотим выразить огромную благодарность стоматологической клинике
Осмотр, консультация от 150 руб.
Рентгеновский снимок от 100 руб.
dentavita03.ru
Наши цены Отзывы
Реклама помогает поддерживать
и развивать наш сервис.


Подробнее
(ссылка откроется в новой вкладке)
  Реклама