Всем привет!
На днях столкнулся с необходимостью вывода товаров из нескольких Инфоблоков с возможностью сортировки и фильтрации (в моем случаем фильтрации по цене). Хочу поделиться кодом.
Надеюсь кому-то пригодится.
На днях столкнулся с необходимостью вывода товаров из нескольких Инфоблоков с возможностью сортировки и фильтрации (в моем случаем фильтрации по цене). Хочу поделиться кодом.
class CIBlockElementMulti { /** * Функция для получения товаров из нескольких инфоблоков с получением и сортировкой свойств * Функциональность ограничена, в частных случаях возможно потребует доработки * * @param array $arOrder * @param array $arFilter * @param bool|array $arGroupBy * @param bool|array $arNavStartParams * @param array $arSelectFields * * @return integer|CIBlockResult */ public function GetList( $arOrder = ["SORT" => "ASC"], $arFilter = [], $arGroupBy = false, $arNavStartParams = false, $arSelectFields = [] ) { global $DB; $sWhere = ""; if (!is_array($arFilter["IBLOCK_ID"])) { return false; } $sSql = " SEL ECT BE.ID AS ID, BE.IBLOCK_ID AS IBLOCK_ID, B.CODE AS IBLOCK_CODE, BE.IBLOCK_SECTION_ID AS IBLOCK_SECTION_ID, "; $sPropSql = ""; foreach ($arSelectFields as $arField) { if (strpos($arField, "PROPERTY_") === false) { continue; } $arProps = []; foreach ($arFilter["IBLOCK_ID"] as $iIblockId) { $dbRes = \CIBlockProperty::GetList(false, [ "ACTIVE" => "Y", "IBLOCK_ID" => $iIblockId, "CODE" => str_replace("PROPERTY_", "", $arField), ]); if ($arProp = $dbRes->GetNext()) { $arProps[] = "FPS".$iIblockId.".PROPERTY_".$arProp["ID"]; } } if (!$arProps) { $arProps [] ="''"; } $sPropSql .= " coalesce(".join(",", $arProps).") AS ".$arField."_VALUE, \r\n"; } $sSql .= $sPropSql; foreach ($arFilter as $sKey => $arValue) { if (strpos($sKey, ">CATALOG_PRICE") !== false) { $iPriceId = explode("CATALOG_PRICE_", $sKey)[1]; $sWhere .= " AND ((((CAT_P".$iPriceId.".PRICE > '".$arValue."'))))"; }elseif (is_numeric($sKey) and is_array($arValue)) { if (isset($arValue["LOGIC"])) { $sLogic = $arValue["LOGIC"]; unset($arValue["LOGIC"]); $arTmp = []; foreach ($arValue as $arVal2) { $sKey2 = key($arVal2); $arVal2 = reset($arVal2); if (strpos($sKey2, "CATALOG_PRICE") !== false) { $iPriceId = explode("CATALOG_PRICE_", $sKey2)[1]; $arTmp[] = "((((CAT_P".$iPriceId.".PRICE BETWEEN '".$arVal2[0]."' AND '".$arVal2[1]."'))))"; } } if ($arTmp) { $sWhere .= " AND (".join(" ".$sLogic." ", $arTmp).") "; } } } elseif ($sKey == "IBLOCK_ID" || $sKey == "ID") { if (is_array($arValue)) { $iIds = join("','", $arValue); } else { $iIds = $arValue; } $sWhere.=" AND BE.".$sKey." IN ('".$iIds."')"; } elseif ($sKey == "ACTIVE") { $sWhere .= " AND BE.ACTIVE = '".$arFilter["ACTIVE"]."'"; } } if ($iPriceId) { $sSql .= " CAT_P".$iPriceId.".ID AS CATALOG_PRICE_ID_".$iPriceId.", CAT_P".$iPriceId.".CATALOG_GROUP_ID AS CATALOG_GROUP_ID_".$iPriceId.", CAT_P".$iPriceId.".PRICE AS CATALOG_PRICE_".$iPriceId.", CAT_P".$iPriceId.".CURRENCY AS CATALOG_CURRENCY_".$iPriceId.", CAT_P".$iPriceId.".QUANTITY_FROM AS CATALOG_QUANTITY_FROM_".$iPriceId.", CAT_P".$iPriceId.".QUANTITY_TO AS CATALOG_QUANTITY_TO_".$iPriceId.", 'Y' AS CATALOG_CAN_ACCESS_".$iPriceId.", 'Y' AS CATALOG_CAN_BUY_".$iPriceId.", CAT_P".$iPriceId.".EXTRA_ID AS CATALOG_EXTRA_ID_".$iPriceId.", \r\n"; } $sSql .= " CAT_PR.QUANTITY AS CATALOG_QUANTITY, CAT_PR.QUANTITY_RESERVED AS CATALOG_QUANTITY_RESERVED, IF (CAT_PR.QUANTITY_TRACE = 'D', 'N', CAT_PR.QUANTITY_TRACE) AS CATALOG_QUANTITY_TRACE, CAT_PR.QUANTITY_TRACE AS CATALOG_QUANTITY_TRACE_ORIG, IF (CAT_PR.CAN_BUY_ZERO = 'D', 'Y', CAT_PR.CAN_BUY_ZERO) AS CATALOG_CAN_BUY_ZERO, CAT_PR.CAN_BUY_ZERO AS CATALOG_CAN_BUY_ZERO_ORIG, IF (CAT_PR.NEGATIVE_AMOUNT_TRACE = 'D', 'Y', CAT_PR.NEGATIVE_AMOUNT_TRACE) AS CATALOG_NEGATIVE_AMOUNT_TRACE, CAT_PR.NEGATIVE_AMOUNT_TRACE AS CATALOG_NEGATIVE_AMOUNT_ORIG, IF (CAT_PR.SUBSCRIBE = 'D', 'Y', CAT_PR.SUBSCRIBE) AS CATALOG_SUBSCRIBE, CAT_PR.SUBSCRIBE AS CATALOG_SUBSCRIBE_ORIG, CAT_PR.AVAILABLE AS CATALOG_AVAILABLE, CAT_PR.WEIGHT AS CATALOG_WEIGHT, CAT_PR.WIDTH AS CATALOG_WIDTH, CAT_PR.LENGTH AS CATALOG_LENGTH, CAT_PR.HEIGHT AS CATALOG_HEIGHT, CAT_PR.MEASURE AS CATALOG_MEASURE, CAT_VAT.RATE AS CATALOG_VAT, CAT_PR.VAT_ID AS CATALOG_VAT_ID, CAT_PR.VAT_INCLUDED AS CATALOG_VAT_INCLUDED, CAT_PR.PRICE_TYPE AS CATALOG_PRICE_TYPE, CAT_PR.RECUR_SCHEME_TYPE AS CATALOG_RECUR_SCHEME_TYPE, CAT_PR.RECUR_SCHEME_LENGTH AS CATALOG_RECUR_SCHEME_LENGTH, CAT_PR.TRIAL_PRICE_ID AS CATALOG_TRIAL_PRICE_ID, CAT_PR.WITHOUT_ORDER AS CATALOG_WITHOUT_ORDER, CAT_PR.SELECT_BEST_PRICE AS CATALOG_SELECT_BEST_PRICE, CAT_PR.PURCHASING_PRICE AS CATALOG_PURCHASING_PRICE, CAT_PR.PURCHASING_CURRENCY AS CATALOG_PURCHASING_CURRENCY, CAT_PR.TYPE AS CATALOG_TYPE, CAT_PR.BUNDLE AS CATALOG_BUNDLE FR OM b_iblock B INNER JOIN b_lang L ON B.LID = L.LID INNER JOIN b_iblock_element BE ON BE.IBLOCK_ID = B.ID "; foreach ($arFilter["IBLOCK_ID"] as $iIblockId) { $sSql .= " LEFT JOIN b_iblock_element_prop_s".$iIblockId." FPS".$iIblockId." ON FPS".$iIblockId.".IBLOCK_ELEMENT_ID = BE.ID \r\n"; } if ($iPriceId) { $sSql .= " LEFT JOIN b_catalog_price CAT_P".$iPriceId." ON(CAT_P".$iPriceId.".PRODUCT_ID = BE.ID AND CAT_P".$iPriceId.".CATALOG_GROUP_ID = ".$iPriceId.") \r\n"; } $sSql .= " LEFT JOIN b_catalog_product CAT_PR ON(CAT_PR.ID = BE.ID) LEFT JOIN b_catalog_iblock CAT_IB ON((CAT_PR.VAT_ID IS null OR CAT_PR.VAT_ID = 0) AND CAT_IB.IBLOCK_ID = BE.IBLOCK_ID) LEFT JOIN b_catalog_vat CAT_VAT ON(CAT_VAT.ID = IF ((CAT_PR.VAT_ID IS null OR CAT_PR.VAT_ID = 0), CAT_IB.VAT_ID, CAT_PR.VAT_ID)) WHERE 1 = 1 ".$sWhere."\r\n"; if (!$arFilter["IBLOCK_ID_FULL_LIST"] and is_array($arFilter["IBLOCK_ID"]) and sizeof($arFilter["IBLOCK_ID"])>1) $sPreOrder = "IBLOCK_ID asc, "; if (strpos(key($arOrder), "PROPERTY_") !== false) { $sOrderBy = "ORDER BY ".$sPreOrder.key($arOrder)."_VALUE ".reset($arOrder); } elseif (stristr(key($arOrder),"CATALOG")) { $sOrderBy = "ORDER BY ".$sPreOrder.key($arOrder)." ".reset($arOrder); } else { $sOrderBy = "ORDER BY ".$sPreOrder."BE.".key($arOrder)." ".reset($arOrder); } if ($sOrderBy) { $sOrderBy .= ", ID DESC"; } $sSql .= " AND (((BE.WF_STATUS_ID = 1 AND BE.WF_PARENT_ELEMENT_ID IS null))) ".$sOrderBy; $obResCnt = $DB->Query($sSql, false, __LINE__); $iCnt = $obResCnt->SelectedRowsCount(); $obRes = new \CDBResult(); $obRes->NavQuery($sSql, $iCnt, $arNavStartParams); $obRes = new \CIBlockResult($obRes); return $obRes; } } |