Битрикс очень старый. И поведение старых компонентов не меняет, боится поломать совместимость. Сейчас покажу, за что в Битрикс кидают какашками, и как это исправить.
Нынешняя проблема характерна для актуальной 25.600.0 версии главного модуля для компонентов bitrix:system.pagenavigation в bitrix:news.list в ЧПУ настроенном вручную. Что может пойти не так в компонентах, которым по 20 лет, и которые должны быть отлажены?
Для bitrix:system.pagenavigation в bitrix:catalog.section такой проблемы нет
Пожалуйста посмотрите статью В ней устаревшая функция $APPLICATION->GetCurPageParam() формирует url с параметрами из $_GET. Это совершенно неправильно.
bitrix:system.pagenavigation тоже формирует параметры из $_GET. Очень трудно использовать этот компонент с ЧПУ через urlerewrite. В постраничной навигации на странице /catalog/tires/ будут ссылки вида /catalog/tires/?SECTION_CODE=tires&PAGEN_1=2
Причина в компоненте bitrix:system.pagenavigation, где такой код:
Конкретно DeleteParam не удаляет, а прибавляет параметры в url. htmlspecialcharsbx здесь тоже не нужна
Сначала DeleteParam прибавляет все параметры из $_GET а потом удаляет некоторые
Причём эта проблема есть в bitrix:news.list, в bitrix:catalog.section её нет
Обратите внимание - поведение компонента зависит исключительно от наличия $arParams["BASE_LINK"]. bitrix:catalog.section передаёт параметр, а news.list не передаёт
Конечно, Битрикс должен исправить свой компонент навигации. Нельзя прибавлять параметры из $_GET.
Но пока есть 2 варианта исправить
1. Исправление в параметрах news.list - рекомендуемый Битриксом, но не совсем хороший способ
Сейчас мы можем посчитать за Битрикс страницу, относительно которой строить навигацию.
"PAGER_BASE_LINK_ENABLE" => "Y",
"PAGER_BASE_LINK" => $url,
Это надо делать на всех страницах, где есть компонент списка новостей.
Можно явно, если все параметры убрать - такой способ решит большинство проблем (кроме задач с фильтрами)
Но если есть фильтр, то надо повозиться. Можно все параметры убирать, кроме нужных. Можно убирать только служебные.
Один из примеров - убрать все служебные параметры: это работает в нашем примере для PAGEN_1.
Вызов компонента
(фото во вложении)
2. Исправление в шаблоне system.pagenavigation - хороший способ, если надо сохранить параметры url, кроме системных
Надо в шаблоне сделать свой result_modifier.php и посчитать в нём заново url. Этот код пишем в одном месте и используем во всех компонентах свой шаблон навигации.
Этот способ универсальный. Он знает свой номер PAGEN_
Нынешняя проблема характерна для актуальной 25.600.0 версии главного модуля для компонентов bitrix:system.pagenavigation в bitrix:news.list в ЧПУ настроенном вручную. Что может пойти не так в компонентах, которым по 20 лет, и которые должны быть отлажены?
Для bitrix:system.pagenavigation в bitrix:catalog.section такой проблемы нет
Пожалуйста посмотрите статью В ней устаревшая функция $APPLICATION->GetCurPageParam() формирует url с параметрами из $_GET. Это совершенно неправильно.
bitrix:system.pagenavigation тоже формирует параметры из $_GET. Очень трудно использовать этот компонент с ЧПУ через urlerewrite. В постраничной навигации на странице /catalog/tires/ будут ссылки вида /catalog/tires/?SECTION_CODE=tires&PAGEN_1=2
Причина в компоненте bitrix:system.pagenavigation, где такой код:
$arResult["NavQueryString"] = htmlspecialcharsbx(DeleteParam($delParam)); |
Сначала DeleteParam прибавляет все параметры из $_GET а потом удаляет некоторые
function DeleteParam($ParamNames)
{
if (empty($_GET))
{
return '';
}
$aParams = $_GET;
foreach (array_keys($aParams) as $key)
{
foreach ($ParamNames as $param)
{
if (strcasecmp($param, $key) == 0)
{
unset($aParams[$key]);
break;
}
}
}
return http_build_query($aParams, "", "&");
}
|
Причём эта проблема есть в bitrix:news.list, в bitrix:catalog.section её нет
Обратите внимание - поведение компонента зависит исключительно от наличия $arParams["BASE_LINK"]. bitrix:catalog.section передаёт параметр, а news.list не передаёт
if(($arParams["BASE_LINK"] ?? '') <> '')
{
if(($pos = mb_strpos($arParams["BASE_LINK"], "?")) !== false)
{
$arResult["sUrlPath"] = mb_substr($arParams["BASE_LINK"], 0, $pos);
$arResult["NavQueryString"] = mb_substr($arParams["BASE_LINK"], $pos + 1);
}
else
{
$arResult["sUrlPath"] = $arParams["BASE_LINK"];
$arResult["NavQueryString"] = "";
}
}
else
{
$arResult["sUrlPath"] = GetPagePath(false, false);
$delParam = array_merge(
array(
"PAGEN_".$dbresult->NavNum,
"SIZEN_".$dbresult->NavNum,
"SHOWALL_".$dbresult->NavNum,
"PHPSESSID",
),
\Bitrix\Main\HttpRequest::getSystemParameters()
);
$arResult["NavQueryString"] = htmlspecialcharsbx(DeleteParam($delParam));
}
$arResult['sUrlPathParams'] = $arResult['sUrlPath'].'?'.($arResult['NavQueryString'] <> ''? $arResult['NavQueryString'].'&' : '');
|
Конечно, Битрикс должен исправить свой компонент навигации. Нельзя прибавлять параметры из $_GET.
Но пока есть 2 варианта исправить
1. Исправление в параметрах news.list - рекомендуемый Битриксом, но не совсем хороший способ
Сейчас мы можем посчитать за Битрикс страницу, относительно которой строить навигацию.
"PAGER_BASE_LINK_ENABLE" => "Y",
"PAGER_BASE_LINK" => $url,
Это надо делать на всех страницах, где есть компонент списка новостей.
Можно явно, если все параметры убрать - такой способ решит большинство проблем (кроме задач с фильтрами)
$url = "/news/"; |
Но если есть фильтр, то надо повозиться. Можно все параметры убирать, кроме нужных. Можно убирать только служебные.
Один из примеров - убрать все служебные параметры: это работает в нашем примере для PAGEN_1.
<? $arDeleteParams = [ "PHPSESSID", "PAGEN_1", "SIZEN_1", "SHOWALL_1", //"PAGEN_2", "SIZEN_2", "SHOWALL_2", ]; $arDeleteSystemParams = \Bitrix\Main\HttpRequest::getSystemParameters(); $arDeleteParams = array_merge( $arDeleteParams, $arDeleteSystemParams); // https://dev.1c-bitrix.ru/community/webdev/user/25773/blog/45676/ // можно $url = getCurPageParamD7( [],$arDeleteParams ); $request = \Bitrix\Main\Application::getInstance()->getContext()->getRequest(); $uriString = $request->getRequestUri(); $uri = new \Bitrix\Main\Web\Uri($uriString); $uri->deleteParams($arDeleteParams); // ничего не добавляем $uri->addParams($arAddParams); $url = $uri->getUri(); ?> |
Вызов компонента
<?$APPLICATION->IncludeComponent( "bitrix:news.list", ".default", [ *** "PAGER_BASE_LINK_ENABLE" => "Y", "PAGER_BASE_LINK" => $url, "PAGER_PARAMS_NAME" => "arrPager" ], false );?> |
2. Исправление в шаблоне system.pagenavigation - хороший способ, если надо сохранить параметры url, кроме системных
Надо в шаблоне сделать свой result_modifier.php и посчитать в нём заново url. Этот код пишем в одном месте и используем во всех компонентах свой шаблон навигации.
Этот способ универсальный. Он знает свой номер PAGEN_
<?php if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
//echo $arParams["BASE_LINK"]
// Askaron заново вычисляем путь, потому что стандартный компонент берёт url из $_GET и не работает нормально с ЧПУ
// Мы хотим убрать SECTION_CODEиз ссылок
// Вместо /catalog/tires/?SECTION_CODE=tires&PAGEN_1=2 сделать /catalog/tires/?PAGEN_1=2
// Если было $arResult["NavQueryString"] = htmlspecialcharsbx(DeleteParam($delParam));
$delParam = array_merge(
array(
"PAGEN_".$arResult["NavNum"],
"SIZEN_".$arResult["NavNum"],
"SHOWALL_".$arResult["NavNum"],
"PHPSESSID",
),
\Bitrix\Main\HttpRequest::getSystemParameters()
);
$path = "";
$request = \Bitrix\Main\Application::getInstance()->getContext()->getRequest();
$uriString = $request->getRequestUri();
$uri = new \Bitrix\Main\Web\Uri($uriString);
$uri->deleteParams($delParam);
//$arResult[ "sUrlPathParamsNoPagen" ] = $uri->getUri();
$arResult[ "sUrlPath" ] = $uri->getPath();
$arResult[ "NavQueryString" ] = $uri->getQuery();
$arResult[ "sUrlPathParams_no_last_amp" ] = $uri->getUri();
$arResult[ "sUrlPathParams" ] = $arResult[ "sUrlPathParams_no_last_amp" ];
if ( mb_strlen( $uri->getQuery() ) > 0 )
{
$arResult[ "sUrlPathParams" ] .= "&";
}
else
{
$arResult[ "sUrlPathParams" ] .= "?";
}
// Если хотим, чтобы не было ошибок валидатора:
//$arResult[ "~NavQueryString" ] = $arResult[ "NavQueryString" ];
//$arResult[ "~sUrlPathParams" ] = $arResult[ "sUrlPathParams" ];
//$arResult[ "NavQueryString" ] = htmlspecialcharsbx($arResult[ "~NavQueryString" ]);
//$arResult[ "sUrlPathParams" ] = htmlspecialcharsbx($arResult[ "~sUrlPathParams" ]); |