Greetings. There is such a problem in the bitrix - there is a search for search.title headers. It is necessary that he did not index the goods, which have no commercial offers in warehouses. I wrote the code on the test page, I drive in the product ID manually - everything shows correctly, whether there is a TP and everything seems to be good. Well, then in init.php I cause an event before indexing and in the same way I try to exclude unnecessary goods, but still they somehow pass. What could be the problem?

AddEventHandler("search", "BeforeIndex", "BeforeIndexHandler"); function BeforeIndexHandler($arFields) { CModule::IncludeModule('iblock'); CModule::IncludeModule('catalog'); $TovarExist = false; $TypeProduct = CCatalogSKU::getOffersList($arFields['ID']); if($TypeProduct != false){ foreach($TypeProduct as $key => $ProdSku){ foreach($ProdSku as $key => $SkuID){ for ($i = 2; $i < 12; $i++) { if ($i !== 8 && $i !== 9) { // неактивные склады $rsStore = CCatalogStoreProduct::GetList(array(), array('PRODUCT_ID' =>$SkuID['ID'], 'STORE_ID' => $i), false, false, array()); $arStore = $rsStore->Fetch(); if($arStore['AMOUNT'] > 0){ $TovarExist = true; } } } } } } if($TovarExist === false){ $arFields["BODY"] = $arFields["TITLE"] = ''; unset($arFields["BODY"]); //на всякий случай unset($arFields["TITLE"]); } 

}

    2 answers 2

    First: the handler needs to pass &$arFields . Secondly, you run through the cycle by setting the flag, and check it when you drop out of the cycle, that is, you work only with the last value of the flag. For some reason it seems to me that it should be like this:

     ... if ($arStore['AMOUNT'] < 0) { $arFields['BODY'] = $arFields['TITLE'] = ''; unset($arFields['BODY'], $arFields['TITLE']); } ... 

    In unset you can pass any number of arguments. and reduce the number of treated conditions. To handle warehouses, you can also make a simplification. Remove to hell for . Create an array with warehouses. You can even create it using the API by selecting only the active warehouses CCatalogStore::GetList(array(), array("ACTIVE" => "Y"), array('ID') , well, or something like that, here's the dock . And via in_array() check. if works faster than for . The fewer the cycles, the faster the script is executed.

    • Firstly, your advice did not help, and secondly, I do script optimization only after it starts working; I did not ask anything about this. Thirdly, if you could deal with the script more attentively, you would see that the flag is set ONLY when there is a sales offer in some warehouse, otherwise the flag is not set, which was what I needed. - Grekov Ilya
    • The flag is completely useless. It is easier to check for less in the loop and immediately perform an action, why in other case set the flag, and then still perform the desired action. With the flag, you get 2 extra actions. Optimization needs to be addressed immediately before writing the code. The structure of the algorithm should be optimal without actions that, in general, do not affect its work. In your case, such an action is setting a flag. Well, you can get the necessary ID of warehouses through the API. But this is your business. - Nikolaj Sarry
    • And what action do you propose to perform "immediately in a cycle"? If there is no one in one warehouse, then immediately delete from indexing or how? - Grekov Ilya
    • Why on one? You can immediately check the availability of goods in all the necessary warehouses. In CCatalogStoreProduct::GetList pass the PRODUCT_ID and =AMOUNT=>0 to the filter. Let it return only warehouse identifiers. And then after how many warehouses there returned to you. If all the warehouses are, then immediately delete the indexing, if not all, then leave. It makes no sense to sort out warehouses. Or send to CCatalogStoreProduct::GetList in the filter also an array of necessary warehouses. It makes no sense to sort out the warehouse. - Nikolaj Sarry
    • And, everything, understood, a good idea, thanks :) - Grekov Ilya

    The problem was solved by adding $arFields["TAGS"] = '';