В одном давнишнем проекте по техническому заданию необходимо было иметь группы товаров и, собственно, сами товары. Были созданы два информационных блока - Группа и Товар. Для групп создано свойство множественной привязки к товарам. Для удобства захотелось как для групп задавать список товаров, так и для товаров менять группы.
Клонируем:
github
Попробуем познакомиться с github, выложим туда получившийся код. Заимев аккаунт на github можно приступать к работе с git.Клонируем:
asvavilov@asvavilov-desktop:~/projects$ git clone https://github.com/asvavilov/bitrix-relations.gitДобавляем файлы в репозиторий:
Cloning into 'bitrix-relations'...remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
asvavilov@asvavilov-desktop:~/projects$ cd bitrix-relations/
asvavilov@asvavilov-desktop:~/projects/bitrix-relations$ ls
README.md
asvavilov@asvavilov-desktop:~/projects/bitrix-relations$ git status
# On branch master
nothing to commit (working directory clean)
asvavilov@asvavilov-desktop:~/projects/bitrix-relations$ git log
commit 5068a0f0f3026196f1855f9760abee26d6454526
Author: Alexander Vavilov <vavilov.rf@gmail.com>
Date: Sun Jul 15 11:52:50 2012 -0700
Initial commit
asvavilov@asvavilov-desktop:~/projects/bitrix-relations$ git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# init.php
nothing added to commit but untracked files present (use "git add" to track)
asvavilov@asvavilov-desktop:~/projects/bitrix-relations$ git add .
asvavilov@asvavilov-desktop:~/projects/bitrix-relations$ git commit -m 'initial-2'
[master 03eec92] initial-2
1 file changed, 163 insertions(+)
create mode 100644 init.php
Отправляем в репозиторий на github:
asvavilov@asvavilov-desktop:~/projects/bitrix-relations$ git push origin master:master
Username for 'https://github.com': asvavilov
Password for 'https://asvavilov@github.com':
To https://github.com/asvavilov/bitrix-relations.git
5068a0f..03eec92 master -> master
bitrix
Далее код с комментариями (последняя версия размещена здесь: https://github.com/asvavilov/bitrix-relations/):/*
* реализация связи "один-ко-многим"
* https://github.com/asvavilov/bitrix-relations/
* TODO:
* - можно сделать универсальней, чтобы другие отношения поддерживались
* - вынести отдельно коды инфоблоков и свойств
* - отвязать код от групп и продуктов
*/
// регистрируем обработчики событий
AddEventHandler("iblock", "OnAfterIBlockElementAdd", array("MyRelations", "OnAfterIBlockElementAddHandler"));
AddEventHandler("iblock", "OnAfterIBlockElementUpdate", array("MyRelations", "OnAfterIBlockElementUpdateHandler"));
AddEventHandler("iblock", "OnAfterIBlockElementDelete", array("MyRelations", "OnAfterIBlockElementDeleteHandler"));
CModule::IncludeModule("iblock");
/**
* bitrix-relations
*/
class MyRelations
{
/**
* Возвращает инфоблок по идентикатору
*/
function getRelatedIBlock($iblock_id)
{
$res = CIBlock::GetByID($iblock_id);
return $res->GetNext();
}
/**
* Сохраняет группу
*/
function save_group($arFields, $iblock)
{
$res = CIBlockProperty::GetList(array(), array("IBLOCK_ID"=>$iblock["ID"], "CODE"=>"PRODUCTS"));
$prop_products = $res->GetNext();
if (!$prop_products) return ;
$res = $arFields["PROPERTY_VALUES"][$prop_products["ID"]];
$product_ids = array();
if ($res)
{
foreach ($res as $row)
{
if (!$row["VALUE"]) continue;
$product_ids[$row["VALUE"]] = $row["VALUE"];
}
}
self::resetProductsGroup($arFields["ID"], $product_ids);
if ($product_ids)
{
foreach ($product_ids as $product_id)
{
if (!$product_id) continue;
$arFilter = array("IBLOCK_CODE"=>"product", "ID"=>$product_id, "PROPERTY_GROUP"=>$arFields["ID"]);
$res = CIBlockElement::GetList(array(), $arFilter);
$already_child_product = $res->GetNext();
if ($already_child_product) continue;
CIBlockElement::SetPropertyValuesEx($product_id, false, array("GROUP" => $arFields["ID"]));
}
}
}
/**
* Сбрасывает продукты для группы
*/
function resetProductsGroup($group_id, $product_ids = array())
{
if (!$group_id) return ;
$arFilter = array("IBLOCK_CODE"=>"product", "PROPERTY_GROUP"=>$group_id);
$res = CIBlockElement::GetList(array(), $arFilter, false, false, array());
while($prev_product = $res->GetNext())
{
if ($product_ids[$prev_product["ID"]]) continue;
CIBlockElement::SetPropertyValuesEx($prev_product["ID"], false, array("GROUP" => null));
}
}
/**
* Сохраняет продукт
*/
function save_product($arFields, $iblock)
{
$res = CIBlockProperty::GetList(array(), array("IBLOCK_ID"=>$iblock["ID"], "CODE"=>"GROUP"));
$prop_group = $res->GetNext();
if (!$prop_group) return ;
$res = $arFields["PROPERTY_VALUES"][$prop_group["ID"]];
$group_ids = array();
if ($res)
{
foreach ($res as $row)
{
if (!$row["VALUE"]) continue;
$group_ids[$row["VALUE"]] = $row["VALUE"];
}
}
self::resetGroupProduct($arFields["ID"], $group_ids);
if ($group_ids)
{
foreach ($group_ids as $group_id)
{
if (!$group_id) continue;
$res = CIBlockElement::GetByID($group_id);
$group = $res->GetNextElement();
if (!$group) continue;
$prop_products = $group->GetProperty("PRODUCTS");
$product_ids = $prop_products["VALUE"];
if (in_array($arFields["ID"], $product_ids)) continue;
$product_ids[] = $arFields["ID"];
$prop_products = array();
foreach ($product_ids as $product_id)
{
$prop_products[] = array("VALUE"=>$product_id);
}
CIBlockElement::SetPropertyValuesEx($group_id, false, array("PRODUCTS" => $prop_products));
}
}
}
/**
* Сбрасывает группу для продукта
*/
function resetGroupProduct($product_id, $group_ids = array())
{
if (!$product_id) return ;
$arFilter = array("IBLOCK_CODE"=>"group", "PROPERTY_PRODUCTS"=>$product_id);
$res = CIBlockElement::GetList(array(), $arFilter, false, false, array());
while($prev_group = $res->GetNextElement())
{
$fields = $prev_group->GetFields();
if ($group_ids[$fields["ID"]]) continue;
$prop_products = $prev_group->GetProperty("PRODUCTS");
$product_ids = $prop_products["VALUE"];
if (!in_array($product_id, $product_ids)) continue;
$prop_products = array();
foreach ($product_ids as $p_id)
{
if ($p_id == $product_id) continue;
$prop_products[] = array("VALUE"=>$p_id);
}
CIBlockElement::SetPropertyValuesEx($fields["ID"], false, array("PRODUCTS" => $prop_products));
}
}
/**
* Обработчик события OnAfterIBlockElementAdd
*/
function OnAfterIBlockElementAddHandler(&$arFields)
{
if (!$arFields["RESULT"]) return ;
$iblock = self::getRelatedIBlock($arFields["IBLOCK_ID"]);
if (!$iblock) return ;
switch ($iblock["CODE"])
{
case "group":
self::save_group($arFields, $iblock);
break;
case "product":
self::save_product($arFields, $iblock);
break;
}
}
/**
* Обработчик события OnAfterIBlockElementUpdate
*/
function OnAfterIBlockElementUpdateHandler(&$arFields)
{
if (!$arFields["RESULT"]) return ;
$iblock = self::getRelatedIBlock($arFields["IBLOCK_ID"]);
if (!$iblock) return ;
switch ($iblock["CODE"])
{
case "group":
self::save_group($arFields, $iblock);
break;
case "product":
self::save_product($arFields, $iblock);
break;
}
}
/**
* Обработчик события OnAfterIBlockElementDelete
*/
function OnAfterIBlockElementDeleteHandler($element)
{
$iblock = self::getRelatedIBlock($element["IBLOCK_ID"]);
if (!$iblock) return ;
switch ($iblock["CODE"])
{
case "group":
self::resetProductsGroup($element["ID"]);
break;
case "product":
self::resetGroupProduct($element["ID"]);
break;
}
}
}
Хороший код, дописал TODO, если интересно могу отправить.
ОтветитьУдалитьНа github есть TODO, могу, конечно, и твое добавить. А вообще, развивать не планирую. Можешь форкать или делать pull request.
Удалить