Кастомизируем пагинацию страниц в Opencart 2.3

Внимание.

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

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

Пагинация?

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

Стандартный вид пагинации в Opencart представляет собой следующий блок:

Стандартная пагинация Opencart

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

В данном примере мы превратим стандарную навигацию в пагинацию следующего вида:

Кастомная пагинация Opencart

Изменяем шаблон

Блок с пагинацией встречается в Opencart, как минимум, в следующих шаблонах:

  • category.tpl
  • search.tp
  • manufacturer_info.tpl
  • review.tpl
  • special.tpl

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

На стандартной теме Opencart пагинация выводится в одноименном блоке и представляет собой следующую конструкцию:

  <div class="row">
    <div class="col-sm-6 text-left"><?php echo $pagination; ?></div>
    <div class="col-sm-6 text-right"><?php echo $results; ?></div>
  </div>

Чтобы убрать отображение блока c информацией о списке выводимых элементов, удалим тег div с переменной $results.

После этого изменим класс у div'а с пагинацией на class="col-sm-12 text-center", тем самым задав ширину данного блока в 12 колонок, а так же центрировав его. В результате получим следующий код:

  <div class="row">
    <div class="col-sm-12 text-center"><?php echo $pagination; ?></div>
  </div>

Где редактируется $pagination в Opencart

Управление пагинацией в Opencart происходит в файле pagination.php по адресу: system/library/pagination.php

Рекомендую сделать бэкап данного файла

В самом начале файла pagination.php мы можем видеть переменные, отвечающие за настройки пагинации.

  public $total = 0; 
  public $page = 1; 
  public $limit = 20;
  public $num_links = 8; // Количество выводимых ссылок
  public $url = ''; 
  public $text_first = '|<'; // Текст для ссылки на самую первую страницу
  public $text_last = '>|'; // Текст для ссылки на самую последнюю страницу
  public $text_next = '>'; // Текст для ссылки на следующую страницу
  public $text_prev = '<'; // Текст для ссылки на предыдущую страницу

Для начала изменим количество ссылок, которые будут выводится в пагинации. Для этого переменной $num_links присвоим значение 6.

Изменим так же символы, для кнопок вперед и назад. Для этих целей мы будем использовать шрифтовые иконки FontAwesome, которые по-умолчанию доступны в Opencart 2.3.

  public $text_next = '<i class="fa fa-angle-right"></i>';
  public $text_prev = '<i class="fa fa-angle-left"></i>';

Если изменения не отображаются на сайте, зайдите в админку и обновите кэш-модификаторов.

Далее, находим условие:

  if ($page > 1) {

    $output .= '<li><a href="' . str_replace(array('&page={page}', '?page={page}', '&page={page}'), '', $this->url) . '">' . $this->>text_first . '</a></li>';
    
    if ($page - 1 === 1) {
      $output .= '<li><a href="' . str_replace(array('&page={page}', '?page={page}', '&page={page}'), '', $this->url) . '">' . $this->text_prev . '</a></li>';
    } else {
      $output .= '<li><a href="' . str_replace('{page}', $page - 1, $this->url) . '">' . $this->text_prev . '</a></li>';
    }
  }

Изменим данное условие следующим образом:

   if ($page > 1) { //Если номер текущей страницы больше 1

    if ($page - 1 === 1) { //Если при этом предыдущая страница, относительно текущей, имеет номер 1
      $output .= '<li><a href="' . str_replace(array('&page={page}', '&page={page}'), '', $this->url) . '">' . $this->text_prev . '</a></li>'; //Выводится кнопка "назад" с ссылкой на 1ю страницу
    } else {
      $output .= '<li><a href="' . str_replace('{page}', $page - 1, $this->url) . '">' . $this->text_prev . '</a></li>'; //Выводится кнопка "назад" с ссылкой на предыдущую страницу
    }
    
    if( $page >= ($num_links - 1) ){ //Если текущая страница больше или равна количеству выводимых ссылок - 1 (в данном случае >=5)
      $output .= '<li><a href="' . str_replace('{page}', '&page={page}', $this->url) . '">' . '1' . '</a></li>'; //Выводим ссылку на первую страницу
      $output .= '<li class="dots"><span>' . '...' . '</span></a></li>'; //Выводим многоточие
    }

  }

Поясню, что происходит в этом условии на примере.

Предположим, что мы находимся на странице с номером 8. Данное значение превышает количество ссылок выводимых в пагинации (8 > 6). Это значит, что мы не видим ссылку на самую первую страницу и нам нужно вывести ее, отделив от основного блока многоточием (или любым другим символом, на ваше усмотрение).

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

Если же мы будем находиться на 5й странице, то ссылку на первую страницу мы видеть перестанем. Соответственно в данном случае ее нужно будет вывести. Поэтому условие и выглядит так: $page >= ($num_links - 1).

Аналогичным образом нам нужно изменить вывод ссылок на последние страницы. Найдем условие:

  if ($page < $num_pages) {
  $output .= '<li><a href="' . str_replace('{page}', $page + 1, $this->url) . '">' . $this->text_next . '</a></li>';
  $output .= '<li><a href="' . str_replace('{page}', $num_pages, $this->url) . '">' . $this->text_last . '</a></li>';
}

И изменим его в соответствие с задумкой:

   if ($page < $num_pages) { // Если номер текущей страницы меньше, чем всего страниц
    if ( ($num_pages - $num_links + 1) < $page){ // Если (всего страниц - количество выводимых ссылок + 1) меньше, чем номер текущей страницы
      $output .= '<li><a href="' . str_replace('{page}', $page + 1, $this->url) . '">' . $this->text_next . '</a></li>'; //Выводим кнопку "далее"
    }
    else {
      $output .= '<li class="dots"><span>' . '...' . '</span></a></li>'; //Выводим многоточие
      $output .= '<li><a href="' . str_replace('{page}', $num_pages, $this->url) . '">' . $num_pages . '</a></li>'; //Выводим ссылку на последнюю страницу
      $output .= '<li><a href="' . str_replace('{page}', $page + 1, $this->url) . '">' . $this->text_next . '</a></li>'; //Выводим кнопку "далее"
    }
}

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

Стилизация

Я не буду подробно останавливаться на данном вопросе и просто приведу стили, которые я применил для пагинации в данном уроке.

  .pagination {
    box-shadow: 0px 0px 15px 2px rgba(0,0,0,0.1);
    border-radius: 5px;
    margin: 30px 0;
  }
  .pagination li {
    display: inline-block;
    border: none;
  }
  .pagination li:hover {
    border: none;
  }
  .pagination>li>a, .pagination>li>span{
    font-size: 14px;
    color: #111;
    border: none;
    float: none;
    font-weight: bold;
    background-color: #fff;
    margin: 0;
    line-height: 100%;
    padding: 8px 10px;
  }
  .pagination li.active span {
    color: #fff;
    float: none;
    border: none; 
    border-radius: 2px;
  }
  .pagination li:hover a {
    color: #111;
    border: none;
  }
  .pagination li:first-child a {
    color: #337AB7;
    border-right: 1px solid rgba(0,0,0, .05);
  }
  .pagination li:last-child a {
    color: #337AB7;
    border-left: 1px solid rgba(0,0,0, .05);
  }
  .pagination li:first-child a:hover {
    border-right: 1px solid transparent;
  }
  .pagination li:last-child a:hover {
    border-left: 1px solid transparent;
  }
  .pagination>li>a:focus, .pagination>li>a:hover, .pagination>li>span:focus, .pagination>li>span:hover {
    color: #111;
    border: none;
  }
  .pagination>.active{
    background-color: #fff;
  }
  .pagination>.active>a, .pagination>.active>a:focus, .pagination>.active>a:hover, .pagination>.active>span, .pagination>.active>span:focus, .pagination>.active>span:hover {
    background-color: #337ab7;
  }

Заключение

По итогу, после всех манипуляций мы имеем вполне неплохую пагинацию:

Пагинация после изменений

Надеюсь, данный пример поможет вам разобраться в принципе работы пагинации в Opencart и видоизменять ее так, как вам нужно.

Удачи!