Всем привет.
Может я бы это и написал в блог, но думаю, что я слишком мелко плаваю по оценкам сообщества, что бы получить внимание там.
Собственно, мои отношения с битриксом успешно протекают уже не мало лет.
Для меня - это замечательный фреймворк, с очень сильной, уже готовой админкой, и невероятным количеством готового, полноценного, законченного функционала, и аналогов для сравнения я не знаю.
До битрикса, да и во время него я работаю на зенде, юии, и кодеигнитере. Каждому проекту - индивидуальный подход же.
Никаких, вообще, проблем с разработкой у меня не возникает, поэтому я тут и редкий гость. Иногда путаюсь в админке, но в коде, редко, благо документация богатейшая.
[B]БЛИЖЕ К ДЕЛУ:[/B]
Новый проект, на битриксе.
Среди прочего будет простой контентный раздел, в котором будут разделы и элементы из выбранного типа инфоблоков.
Решено разместить так:
[I]site.ru/content/#SECTION_PATH#/
site.ru/content/#SECTION_PATH#/#ELEMENT_CODE#/[/I]
То есть [I]#SECTION_PATH# [/I]может быть от любого иб, выбранного типа.
Создал и разместил в [I]site.ru/content/index.php[/I] комплексный компонент mycomponent:content, в который, при вызове, среди прочего передаю тип инфоблоков.
Код у него такой
[CODE]$RequestUri = \Bitrix\Main\HttpApplication::getInstance()->getContext()->getRequest()->getRequestUri();
$RequestPath = parse_url($RequestUri, PHP_URL_PATH);
if(!CModule::IncludeModule("iblock"))
{
ShowError(GetMessage("IBLOCK_MODULE_NOT_INSTALLED"));
return;
}
else
{
$arResult['PAGE'] = SefFindUrlTools::GetSection($arParams["IBLOCK_TYPE"],$RequestPath);
if(!$arResult['PAGE']) $arResult['PAGE'] = SefFindUrlTools::GetElement($arParams["IBLOCK_TYPE"],$RequestPath);
if(!$arResult['PAGE'])
{
ShowError('Not Found');
@define("ERROR_404", "Y");
if($arParams["SET_STATUS_404"]==="Y")
CHTTP::SetStatus("404 Not Found");
};
if($arResult['PAGE']['TYPE']=='SECTION')
$this->IncludeComponentTemplate('section');
elseif($arResult['PAGE']['TYPE']=='ELEMENT')
$this->IncludeComponentTemplate('article');
}
[/CODE]
Уж, простите объяснять код не буду, тут всё предельно очевидно.
Если Вы не поняли код, то и прокомментировать его не сможете, а если авторитетные господа не зажурят моё решение, то сделаю отдельную статью с пояснениями, потому как проблема работы того же bitrix:catalog с несколькими инфоблоками поднимается очень часто.
Теперь класс SefFindUrlTools:
[CODE]class SefFindUrlTools {
function GetSection($iblock_type,$uri,$returnRes=false)
{
$found = false;
$arFilter = array(
"IBLOCK_TYPE"=>$iblock_type,
"GLOBAL_ACTIVE"=>"Y",
"IBLOCK_ACTIVE"=>"Y",
);
$rsSections = CIBlockSection::GetList(null, $arFilter, false);
while($arSection = $rsSections->GetNextElement())
{
$ar_res = $arSection->GetFields();
if($ar_res['SECTION_PAGE_URL'] == $uri)
{
if(!$returnRes)
{
$found['TYPE'] = 'SECTION';
$found['ID'] = $ar_res['ID'];
$found['IBLOCK_ID'] = $ar_res['IBLOCK_ID'];
}
else
{
$found = $ar_res;
}
break;
}
}
if(!$found)
return false;
else
return $found;
}
function GetElement($iblock_type,$uri,$returnRes=false)
{
$found = false;
$arFilter = array(
"IBLOCK_TYPE"=>$iblock_type,
"GLOBAL_ACTIVE"=>"Y",
"IBLOCK_ACTIVE"=>"Y",
);
$rsElements = CIBlockElement::GetList(null, $arFilter);
while($arElement = $rsElements->GetNextElement())
{
$ar_res = $arElement->GetFields();
if($ar_res['DETAIL_PAGE_URL'] == $uri)
{
if(!$returnRes)
{
$found['TYPE'] = 'ELEMENT';
$found['ID'] = $ar_res['ID'];
$found['IBLOCK_ID'] = $ar_res['IBLOCK_ID'];
}
else
{
$found = $ar_res;
}
break;
}
}
if(!$found)
return false;
else
return $found;
}
} [/CODE]
Я понимаю, что предусмотрено не всё, но я хочу понять, стоит ли продолжать в этом духе?
Для контентного раздела, который сейчас уже функционирует на этом коде, мне тут всего достаточно, и я думаю таким же методом сделать компонент торгового каталога.
Откуда вообще такое решение?
Меня на это толкнул CIBlockFindTool, который работает в стандартных компонентах, который по сути является такой же оберткой для GetList, что Section, что Element, но у себя я его разшарил на все инфоблоки указанного типа, и сделал возврат какой мне удобно использовать далее.
В кратце, что бы не морочить голову:
1. Получаю запрошенный адрес.
2. Совершаю поиск по всем иб указанного типа на совпадение с чпу урлом, сначала разделов, потом элементов.
3. При нахождении раздела/элемента - возвращаю его тип (раздел/элемент), ид инфоблока, и id элемента, либо весь объект целиком, при желании.
4. Запускаю нужный шаблон, в зависимости от типа найденного объекта (он сразу получает id элемента и инфоблока, как минимум через arResult), если ничего не найдено, то показываю ошибку. Если возьмусь делать торговый каталог на таком решении, то конечно это действие будет более сложным, да и вообще многое по другому, но в сердце работы ЧПУ будет лежать всё тот же SefFindUrlTools.
[B]Почему я это всё пишу:[/B]
На самом деле, я первый раз столкнулся с проблемой работы компонента с несколькими иб, по типу.
Немного оглядевшись что и как с этим у других, подумал - почему же не сделать по своему, вот так?
Но, для того, как эта проблема везде освещена, меня смущает, что решение может быть таким простым, в своей сути, и я нигде его не встретил.
Разве что-то тут не так?
Вот поэтому я бы и хотел услышать мнения авторитетных людей по этому вопросу.
То есть вопрос не в том, как я это обыграл, естественно, если это актуальное решение, то я разработаю это всё дело далее. А вопрос в самом методе решения, который я использую. Да, он работает. Но, насколько он нормален по Вашему?
И если всё Ok, то хотелось бы узнать, насколько целесообразно обернуть выполнение самого компонента в результирующий кеш?
Большое спасибо за внимание!