Универсальная красивая постраничка на Битрикс, фикс и улучшение

Углубленное изучение Битрикс
  • Универсальная красивая постраничка на Битрикс, фикс и улучшение

    Антон Долганин 7 Августа 2015 13:56 17475
    Два года назад я сделал универсальное решение для создания какой-душе-угодно постранички (например, /catalog/pagen2/). Вот этот пост. Все было хорошо, но в Битрикс 15.5 это сломалось по определенным причинам. Детали под катом.

    Ломалась постраничка в том случае, если вы натравливали ее на компонент, лежащий внутри комплексного. Причиной был вот этот метод, в котором $requestURL передавался равный false, и определялся он уже по методу D7. И грязный хак с REQUEST_URI шел мимо.

    Писал я в техподдержку Битрикс с поиском общего решения, посоветовали только одно - внедряться непосредственно до исполнения Битрикс. Самый правильный способ это сделать, это использовать auto_prepend_file, определив ее в корневом .htaccess.

    Если вы внедряете с нуля технологию, делайте все как в раннем посте, кроме обработчика, его делать не надо, и потом переходите к описанию фикса.

    Если вы уже внедряли ее раньше и пришли за фиксом:

    1. Удаляете обработчик.

    2. Создаете файл /bitrix/pagen.php вот такого содержания:
    http://bxapi.ru/code/j2xQ0LHjrzwGrnf/
    Обратите внимание, код регулярного выражения вам надо поправить согласно вашего правила формирования URL, если он отличается от рассматриваемого здесь варианта (pagen1/).

    3. В файл /.htaccess вписываете такую директиву:
    php_value auto_prepend_file "***/bitrix/pagen.php"
    Где вместо трех звездочек ставите ваш док.рут, узнать который можно хотя бы выполнив такой код в php-консоли: echo $_SERVER["DOCUMENT_ROOT"];
    Файл правьте только посредством ssh/ftp, и обязательно удалите строчку, если сайт оказался нерабочим.

    По идее все должно работать.


    Теперь что насчет улучшения.  $newUrl я получаю немного другим способом, так как боты частенько атаковывали сайт и подмешивали в постраничку различный мусор.
    Вариант первый, это то, что я исправил в прилагаемом файле. Получаем в лоб путь до основной директории постранички из SCRIPT_NAME. Вариант второй, если финт не прокатит по причине динамического URL категории (например, /catalog/tv/, где tv динамика). Тут вам уже самим надо доработать в зависимости от специфики проекта.
    Ну а если боты не атакуют, то и вовсе оставить первый вариант шаблона.
    Файлы:

Дмитрий
12 Августа 2015 11:43
Спасибо за фикс! Только вот есть одна проблемка. В .htaccess уже вписано подключение файла для сканирования Веб-антивирусом до начала буферизации (см. здесь). Поэтому вариант с  auto_prepend_file не получается использовать без потерь. Есть обходные пути еще?
Дмитрий
12 Августа 2015 11:51
PS. пока что приходится на странице компонента перед подключением header подключать pagen.php.
Антон Долганин
12 Августа 2015 12:53
Дмитрий, спасибо за пример ситуации.

Тут два варианта:

1. Инклудить в htaccess один общий файл (не знаю, /bitrix/prepend.php), внутри которого заинклудить нужные вам файлы (в частности проактивки и из поста).

2. Воткнуть в /bitrix/header.php до подключения файла Битрикс файл из поста. Битрикс его никогда не трогает при обновлениях, и он не считается файлом ядра (так что всякие правила вы тоже не нарушите).
Виктор
16 Августа 2015 15:57
Здравствуйте. Попробовал сделать постраничку по Вашему методу. Для списка новстей вообще шикарно:)
Но когда пробую подключить для комплексного компонента - получаю "элемент не найден". Подскажите, в чем можеть быть проблема? Все делал по фиксу.
Антон Долганин
17 Августа 2015 6:04
Виктор, а какой шаблон для просмотра новости у вас и шаблон постранички?
Виктор
17 Августа 2015 8:03
Шаблон постранички - скопированный modern. А шаблон комплексного компонента новостей - стандартный flat.
Виктор
17 Августа 2015 8:08
Шаблоны не кастомизировал, кроме добавления функции в постраничку.
Антон Долганин
17 Августа 2015 14:56
Виктор, я про шаблон URL.
К примеру у меня такой
/content/news/5/38121/
Виктор
17 Августа 2015 15:29
А, все. /news/page-2/
Пробовал оставлять pagen2 - тоже на элемент хочет уходить.
Виктор
17 Августа 2015 16:14
Уже, все, что мог перепробовал(
Антон Долганин
18 Августа 2015 7:21
Виктор, постараюсь выделить время скоро и посмотреть в чем дело.
Виктор
18 Августа 2015 9:33
Антон Долганин
23 Августа 2015 18:49
Виктор, возможно, виной был п.2 в посте, я его поправил (выделил красным), плюс изменил код /bitrix/pagen.php). Имеет смысл перелить этот файл и еще раз проверить.

У меня работает: http://test.d-it.ru/content/news/ , все по инструкции залил.
Алексей
23 Августа 2015 23:14
Здравствуйте!

На моем сайте постраничная навигация находится на динамической странице, к примеру, возьмем раздел /catalog/mezhkomnatnye_dveri/
Я все сделал по инструкции и у меня сформировались ссылки на страницы, вот такого типа: /catalog/pagen2/
которые не листают раздел :(
Как же быть? У меня /catalog/ это папка каталога товаров, /mezhkomnatnye_dveri/ - динамическая страница раздела, который надо листать.
Антон Долганин
24 Августа 2015 4:23
Здравствуйте.
Вы файл шаблона из первого поста скачали или из данного? По идее вам подойдет предыдущий вариант.
Алексей
24 Августа 2015 11:34
Добрый день!
Взял из данного поста, сейчас попробую взять из первого и отпишусь.
Алексей
24 Августа 2015 11:41
Ссылки изменили на ссылки вида "/catalog/mezhkomnatnye_dveri/pagen2/", но страницы не листаются :(
Алексей
24 Августа 2015 11:45
Сорри, заработало! Нужно было разместить повыше строку RewriteRule ^(.*)/pagen([\d]+)/ /$1/?PAGEN_1=$2 [L,QSA] в htaccess в <IfModule mod_rewrite.c>
Алексей
24 Августа 2015 12:31
Антон, добрый день!

Ссылки "/catalog/mezhkomnatnye_dveri/pagen2/" - заработали.
но перестала работать ссылка для отображения сразу всех элементов :(  "/catalog/mezhkomnatnye_dveri/?SHOWALL_1=1"
Как же ее починить? :(
Антон Долганин
25 Августа 2015 4:54
Алексей, тут вам уже конкретно на вашем проекте надо сидеть и разбираться что могло произойти. У меня, к сожалению, идей нет.
Алексей
27 Августа 2015 17:10
Антон, дело в том ,что у меня стандартный шаблон интернет-магазина и я делал все по инструкции.
И кнопка "Все" при это сломалась :(
Антон Долганин
28 Августа 2015 4:44
Алексей, хорошо, прикрепите мне тога шаблон постранички, который у вас получился.
Кирилл
1 Сентября 2015 12:30
Антон, добрый день

Сделал все по Вашему шаблону, по второму, но теперь постранички ссылаются обратно на каталог. Брал первый шаблон, постранички ссылаются на первую страницу, а если второй шаблон, то вовсе на каталог. Делал все по инструкции, не могу понять в чем проблема(
Антон Долганин
2 Сентября 2015 5:35
Кирилл, прикрепите мне архивом: шаблон, .htaccess, подключаемый файл, возможно где-то ошибка в алгоритме все же.
Олег
8 Декабря 2015 20:04
Все было хорошо, но в Битрикс 15.5 это сломалось по определенным причинам
Антон, а что сломалось? Поставил обработчик
AddEventHandler('main', 'OnPageStart', array('CMainhandlers', 'OnPageStartHandler'));

#и правило в htaccess:
RewriteRule ^(.*)/page([\d]+)/ /$1/?PAGEN_1=$2 [L,QSA]


Всё работает, версия 15.5.9.
Олег
8 Декабря 2015 20:30
Всё работало в первом уровне раздела, например /news/page2/, а вот в /news/section/page2/ уже нет (не комплексный компонент).
Всё же добавил pagen.php.

А нет ли в htaceess авто-определения DOCUMENT_ROOT, что бы не писать его явно?
Антон Долганин
9 Декабря 2015 5:31
Всё же добавил pagen.php.
Так у вас ушла проблема или нет?

А нет ли в htaceess авто-определения DOCUMENT_ROOT,
Не слышал о таком :) Это особенность htaccess вроде как такая.
Олег
11 Декабря 2015 20:50
Да, pagen.php как раз и спас.
Про константу htaccess еще погуглил - оказывается там и правда её не может быть из-за особенностей работы самого файла. А хотелось как-то универсально написать :)
Сергей
15 Декабря 2015 10:31
Здравствуйте!. Я использую ваш метод. Все отлично работает в каталоге. Там везде PAGEN_1=xxx. Но в при переходе на страницу поиска там идет нумерация с PAGEN_2=xxx  Страница при клике меняет товары, а вот сама пагинация не листается. Как заставить работать с парамером  PAGEN_2=xxx. Файлы прилагаю в архиве. Вот из init.php


//пагинатор с ЧПУ
AddEventHandler('main', 'OnPageStart', array('CMainhandlers', 'OnPageStartHandler'));
class CMainhandlers {
 
 
  public static function OnPageStartHandler() {
     if (isset($_GET['page'] && intval($_GET['page']>0) {
        $GLOBALS['PAGEN_1'] = $_REQUEST['PAGEN_1'] = $_GET['PAGEN_1'] = $_GET['page'];
        unset($_GET['page'], $_REQUEST['page'], $GLOBALS['page'];
     }
     $GLOBALS['APPLICATION']->reinitPath();
  }
 
}


Заранее благодарен за ответ!
Файлы:
template.php (8.16 КБ)
Антон Долганин
16 Декабря 2015 4:34
Здравствуйте, Сергей.

К сожалению, скрипт работает только с PAGEN_1. Вы можете обратиться к разработчику, чтобы он доплил и до PAGEN_2. По идее, это просто дополнительные условия в коде.
Универсально не сделать.
Сергей
11 Февраля 2016 3:02
Антон, может мне подскажите.
1) Создал файл pagen.php в корне папки bitrix, прописал в нем ваш код.
2) вставляю в .htaccess код по редиректу и файлу pagen.php
3) Применил код шаблона из первой статьи (со второй статьи ссылки формируются неверно). Ссылки формируются верного вида pagen1, pagen2...
Проблема в том, что не переходит по ссылкам. Т.е. перезагрузка страницы происходит, урл в адресной строке меняется, но контент тот же что на первой странице и в пагинации выделена страница 1.
Видел писали об этом люди, но никто не поделился решением этой проблемы. На каком этапе ее искать? Подскажите пожалуйста.
Антон Долганин
11 Февраля 2016 4:09
Сергей,

Если вы внедряете с нуля технологию, делайте все как в раннем посте, кроме обработчика, его делать не надо, и потом переходите к описанию фикса.
А вы конструкцию из прошлого поста делали в htaccess? Именно в прошлом посте еще есть.
Егор
1 Апреля 2016 17:28
Антон здраствуйте.
Не могу разобратся с одной ситуацией. Пагинация работает но частично. Получается что для такого типа URL работает: http://mysite.net/catalog/pagen2/ а вот для http://mysite.net/catalog/mobile/pagen2/ нет. Но не выскакивает ошыбка, а просто не перелистывает страницу и все время находится в 1 разделе. Вчем может быть причина.
Версия битрикс 16.0.9 Бизнес
Спасибо за помощь.
Михаил
7 Июля 2016 11:30
Не пойму что и в какой последовательности надо ставить и фикс куда пихать. Делаю с нуля!
Дмитрий
1 Августа 2016 16:19
Здравствуйте Антон.
Спасибо за ваш скрипт.
Подскажите и где поправить что бы получилось /?pagen2

Заранее спасибо за ответ.
Дмитрий
1 Августа 2016 17:08
.htaccess
RewriteRule ^(.*)/?pagen([\d]+) /$1/?PAGEN_1=$2 [L,QSA]

template
$newUrl .= '?pagen'.intval($v);

Так не срабатывает.
Алекс
22 Сентября 2016 20:09
Антон, здравствуйте!
Все сделали как описано выше с фиксом. Работает везде.
Но есть нюанс, задваивание страниц, то есть работает и по старому:
domen/news/?PAGEN_1=2
и по новому
domen/news/pagen2/

Все бы ничего, но поисковики откуда то берут эти старые ссылки, хотя на сайте их нет.
Все сделали еще в мае месяце, а в поисковиках и дальше появляются ссылки вида ?PAGEN_1=2

Что сделать с этими задвоенными ссылками? Подскажите, пожалуйста!
Антон Долганин
23 Сентября 2016 12:59
Я бы сделал редирект, если это важно. Но старые продолжат работать само собой.
Алекс
4 Февраля 2017 15:47
Еще раз здравствуйте!

Антон, подскажите, как вернуть путь к текущей странице с пагинацией, чтобы использовать страницы типа domen/news/pagen2/ в canonical?
Антон Долганин
5 Февраля 2017 2:54
Здравствуйте.

Разве этот метод не подходит?
$APPLICATION->GetCurPage();
Алекс
9 Февраля 2017 19:16
К сожалению нет,
На странице: domen/news/pagen2/ и domen/news/pagen3/ и т.д.
$APPLICATION->GetCurPage();  выводит domen/news/
Алекс
9 Февраля 2017 19:19
точнее
$APPLICATION->GetCurPage();
выводит просто /news/
без домена и без самих страниц
Иван
12 Мая 2017 16:12
Добрый день, а вы не подскажете как сделать 301 редирект из ?PAGEN_1=* на страницы /pagen*/
Когда я делаю редирект, ложится сайт( Есть какие то у Вас идеи?
* это нумерация страницы:)
Антон Долганин
15 Мая 2017 10:44
Здравствуйте, Иван.

А у вас какой редирект точно записан? (правило)
Иван
15 Мая 2017 10:59
Антон, решил проблему, спасибо!
Альберт
7 Июля 2017 6:57
А у меня в каталоге с комплексным компонентом на странице pagen2/ 404 ошибка выходит не пойму почему
Владимир
28 Августа 2017 16:05
 Здравствуйте,
после добавления строки php_value auto_prepend_file "../bitrix/pagen.php" в .htaccess перестает работать авторизация в административной части, то есть после попытки залогинитьтся страница просто перегружается без полей для ввода, если страницу обновить - то опять форма авторизации. Убирая php_value auto_prepend_file "../bitrix/pagen.php" - авторизация начинает работать нормально(
Антон Долганин
29 Августа 2017 6:57
Здравствуйте, Владимир.

Идей нет. Поможет только отладка. Но с этим не смогу помочь, к сожалению.
Андрей
27 Ноября 2017 9:36
Сделал все как написано, но у меня почему-то получается ссылка вида:
http://доменсайта/pagen3/
А должна получиться:
http://доменсайта/kedrovye-bochky-fytobochky/pagen3/

Подскажите, пожалуйста, почему так?
Андрей
29 Ноября 2017 11:14
Разобрался с сылкой. Теперь она формируется корректно. Но не получается по ней перейти. 404-ю ошибку выдает. Я, кажется, понимаю что проблема в регулярном выражении. Но может подскажите, как его переделать, чтобы можно было попасть, например, по этому пути: http://доменсайта/kedrovye-bochky-fytobochky/pagen3/  
Андрей
29 Ноября 2017 12:04
Блин Тяжело разбираться, если с правилами перенаправления не знаком толком. В общем я все же сделал, что у меня формируется ссылка правильно и перенаправление идет. Вот только какую бы страницу пагинации я не набирал - все равно отображается первая страница.
еще пришлось убрать правило RewriteRule ^(.*)/page([\d]+)/ /$1/?PAGEN_1=$2 [L,QSA] из .htaccess так как из-за него при нажатии на пагинацию, если находишься не на первой странице, создавался дубль /pageN/ в конце адресной строки. Т. е. получалось так /сайт/фитобочки/page1/page4/
Помогите теперь решить вопрос с отображением нужной страницы пагинации, а не всегда первой.
Мурад
18 Декабря 2017 16:48
Приветствую.
Кстати такая же проблема. Ссылка формируется а вот куда не кликни все равно показывает первую.
Руслан
14 Января 2018 8:40
Всем привет, столкнулся с проблемой на хостинге рэг.ру, что по правилу  
RewriteRule ^(.*)/(\d+) /$1/?PAGEN_1=$2 [QSA,L]
картинки по пути сайт/upload/iblock/534/file.png открываются с 403 ошибкой, пришлось выкрутиться, добавив  фильтрацию по файлам, итого работающее правило:
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)/(\d+) /$1/?PAGEN_1=$2 [QSA,L]
Можно добавить в шапку для универсальности решения.
Дмитрий
22 Января 2018 20:05
решение не работает с композитом, все /pagen*/ отдают первую страницу
Василий
2 Февраля 2018 15:17
+1 тоже столкнулся с этой проблемой. Есть ощущение, что произошло после обновления Битрикс.
Игорь
3 Июня 2018 18:52
+ 1 На автокомпозите запускаются страниц со второго раза
Сергей
25 Июля 2018 17:09
Почему-то в блоге на сайте битрикса не добавляется комментарий. Поэтому задам тут.

А разве команда
RewriteRule ^(.*)/pagen([\d]+)/ /$1/?PAGEN_1=$2 [L,QSA]
не прибьет все остальные GET параметры, например, фильтры?
Я $_GET['PAGEN_1'] прописал сразу в файле pagen.php, вроде работает нормально.
Александр
16 Августа 2018 10:46
  у вас последняя версия битрикса? У меня не работает совсем, 404 ошибка
Александр
16 Августа 2018 10:45
404я ошибка, не работает метод а другого не нашел, как сделать ЧПУ или хотя бы страшный гет запрос перевести в нижний регистр?
Александр
30 Ноября 2018 7:42
Здравствуйте. Спасибо за отличное решение! Оно помогло во многих проектах. Может вы сталкивались или адаптировали свое решение под ajax элементы? У меня ajax каталог с ajax фильтрацией, несколько ajax новостных лент. Компоненты стандартные. Сама пагинация генерируется с нужными ссылками вида
catalog/page-n/
При переходе через ссылку с помощью ajax подгрузки в адресной строке возвращается старое PAGEN_1=2. Работают оба варианта ссылок, что для сео очень плохо, нет возможности прикрутить к страницам пагинации назначение правильных метатегов и директив яндекса(но это уже не к пагинации вопрос).

Код файла pagen.php
function __isPathTraversalUri($uri) {
 if (($pos = strpos($uri, '?')) !== false) {
 $uri = substr($uri, 0, $pos);
 }
 
 $uri = trim($uri);
 
 return preg_match("#(?:/|2f|^|\\\\|5c)(??:%0*(25)*2e)|\\.){2,}(?:/|%0*(25)*2f|\\\\|%0*(25)*5c|$)#i", $uri) ? true : false;
}

$newUri = preg_replace('#(page-[\d]+/)#is', '', $_SERVER['REQUEST_URI']

if (!__isPathTraversalUri($newUri)) {
 $_SERVER['REQUEST_URI'] = $newUri;
}
Директивы htaccess:

<IfModule mod_rewrite.c>
   Options +FollowSymLinks
 RewriteEngine On


 php_value auto_prepend_file "path to /bitrix/pagen.php"
    #RewriteRule ^(.*)page-1(.)$ /$1 [R=301,L]
 RewriteRule ^(.*)/page-([\d]+)/ /$1/?PAGEN_1=$2 [L,QSA]

 # Проверяем, повторяется ли слеш (//) более двух раз.
 RewriteCond %{REQUEST_URI} ^(.*)/{2,}(.*)$
 # Исключаем все лишние слеши
 RewriteRule . %1/%2 [R=301,L]

 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-l
 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteCond %{REQUEST_FILENAME} !/bitrix/urlrewrite.php$
 RewriteRule ^(.*)$ /bitrix/urlrewrite.php [L]
 RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]

 #Rewrite from www to host
 RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
 RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

</IfModule>

Если у вас подобных готовых решений нет, то может  подскажите в какую сторону копать? Заранее спасибо
Антон Долганин
5 Декабря 2018 8:37
Александр, здравствуйте.

По аякс не подскажу, к сожалению. Обычно запрашивали данные по аякс-каналу какому-нибудь, который наглухо запрещали к индексации (или даже недоступности кроме как по аякс-запросу).
Алексей
11 Марта 2019 19:37
Вся полезность это этого способа улетучивается, т.к. при композите не работает.
Может есть таки возможность адаптировать под композит?
Сергей
26 Апреля 2019 18:06
Дело в том что для битрикса ссылка /page-2/ не видна. Поэтому композит и отдает страницу с кешем страницы без пагинации. Это конечно печально. Но можете в настройках композита указать параметр PAGEN_1 - при этом композит срабатывать не будет. Но это конечно не решение.
Алексей
1 Июля 2019 15:19
Как выдавать 404 ошибку при несуществующих страницах пагинации?