Работа с местоположениями магазина битрикс d7

Как получить местоположение пользователя мы уже узнали в статье "Определение местоположения d7"

Теперь разберем, как работать с местоположениями в магазине(sale)

Для работы с местоположениями магазина используется класс \Bitrix\Sale\Location\LocationTable

Получение информации о местоположении по ID

$locationItem = \Bitrix\Sale\Location\LocationTable::getById(151167)->fetch();

/* Array
(
    [ID] => 151167
    [CODE] => 0000445112
    [LEFT_MARGIN] => 188545
    [RIGHT_MARGIN] => 188586
    [DEPTH_LEVEL] => 3
    [SORT] => 100
    [PARENT_ID] => 58
    [TYPE_ID] => 5
    [LATITUDE] => 0.000000
    [LONGITUDE] => 0.000000
    [COUNTRY_ID] => 24
    [REGION_ID] => 58
    [CITY_ID] => 151167
    [LOC_DEFAULT] => N
)*/

Получение информации о местоположении по CODE. Фактически это обертка над \Bitrix\Sale\Location\LocationTable::getList(). В отличии от getById() мы можем получить уже больше полей местоположения.

$locationItem = \Bitrix\Sale\Location\LocationTable::getByCode('0000445112', array(
	'filter' => array('=NAME.LANGUAGE_ID' => LANGUAGE_ID),
	'select' => array('*', 'NAME_RU' => 'NAME.NAME')
))->fetch();

/*Array
(
    [ID] => 151167
    [CODE] => 0000445112
    [LEFT_MARGIN] => 188545
    [RIGHT_MARGIN] => 188586
    [DEPTH_LEVEL] => 3
    [SORT] => 100
    [PARENT_ID] => 58
    [TYPE_ID] => 5
    [LATITUDE] => 0.000000
    [LONGITUDE] => 0.000000
    [COUNTRY_ID] => 24
    [REGION_ID] => 58
    [CITY_ID] => 151167
    [LOC_DEFAULT] => N
    [NAME_RU] => Ростов-на-Дону
)*/

Теперь перейдем к основному методу работы с местоположениями: \Bitrix\Sale\Location\LocationTable::getList(). Получим список местоположений с названиями на текущем языке и типами местоположений:

$dbLocationItems = \Bitrix\Sale\Location\LocationTable::getList(array(
	'filter' => array('=NAME.LANGUAGE_ID' => LANGUAGE_ID),
	'select' => array('*', 'NAME_RU' => 'NAME.NAME', 'TYPE_CODE' => 'TYPE.CODE')
));
while($locationItem = $dbLocationItems->fetch())
{
	// ...
}

/*Array
(
    [ID] => 151167
    [CODE] => 0000445112
    [LEFT_MARGIN] => 188545
    [RIGHT_MARGIN] => 188586
    [DEPTH_LEVEL] => 3
    [SORT] => 100
    [PARENT_ID] => 58
    [TYPE_ID] => 5
    [LATITUDE] => 0.000000
    [LONGITUDE] => 0.000000
    [COUNTRY_ID] => 24
    [REGION_ID] => 58
    [CITY_ID] => 151167
    [LOC_DEFAULT] => N
    [NAME_RU] => Ростов-на-Дону
    [TYPE_CODE] => CITY
)*/

Для работы с типами местоположений, используется класс \Bitrix\Sale\Location\TypeTable. Остановимся на нем подробнее позднее.

Получаем потомков указанного местоположения:

$dbLocationItems = \Bitrix\Sale\Location\LocationTable::getList(array(
	'filter' => array(
		'=ID' => 151167, 
		'=CHILDREN.NAME.LANGUAGE_ID' => LANGUAGE_ID,
		'=CHILDREN.TYPE.NAME.LANGUAGE_ID' => LANGUAGE_ID,
	),
	'select' => array(
		"CHILDREN_ID" => 'CHILDREN.ID',
		"CHILDREN_CODE" => 'CHILDREN.CODE',
		'CHILDREN_NAME_RU' => 'CHILDREN.NAME.NAME',
		'CHILDREN_TYPE_CODE' => 'CHILDREN.TYPE.CODE',
		'CHILDREN_TYPE_NAME_RU' => 'CHILDREN.TYPE.NAME.NAME'
	)
));
while($locationItem = $dbLocationItems->fetch())
{
	// ...
}

/*Array
(
    [CHILDREN_ID] => 151168
    [CHILDREN_CODE] => 0000447883
    [CHILDREN_NAME_RU] => свх Ливенцовский 4 отделение посёлок
    [CHILDREN_TYPE_CODE] => VILLAGE
    [CHILDREN_TYPE_NAME_RU] => Село
)*/

Получаем ближайшего родителя указанного местоположения:

$dbLocationItems = \Bitrix\Sale\Location\LocationTable::getList(array(
	'filter' => array(
		'=ID' => 151167, 
		'=PARENT.NAME.LANGUAGE_ID' => LANGUAGE_ID,
		'=PARENT.TYPE.NAME.LANGUAGE_ID' => LANGUAGE_ID,
	),
	'select' => array(
		"I_PARENT_ID" => 'PARENT.ID',
		"I_PARENT_CODE" => 'PARENT.CODE',
		'I_PARENT_NAME_RU' => 'PARENT.NAME.NAME',
		'I_PARENT_TYPE_CODE' => 'PARENT.TYPE.CODE',
		'I_PARENT_TYPE_NAME_RU' => 'PARENT.TYPE.NAME.NAME'
	)
));
while($locationItem = $dbLocationItems->fetch())
{
	// ...
}

/*Array
(
    [I_PARENT_ID] => 58
    [I_PARENT_CODE] => 0000028056
    [I_PARENT_NAME_RU] => Ростовская область
    [I_PARENT_TYPE_CODE] => REGION
    [I_PARENT_TYPE_NAME_RU] => Область
)*/

Получение местоположений от корня дерева до текущего элемента:

$dbLocationItems = \Bitrix\Sale\Location\LocationTable::getList(array(
	'filter' => array(
		'=ID' => 151167, 
		'=PARENTS.NAME.LANGUAGE_ID' => LANGUAGE_ID,
		'=PARENTS.TYPE.NAME.LANGUAGE_ID' => LANGUAGE_ID,
	),
	'select' => array(
		"I_PARENT_ID" => 'PARENTS.ID',
		"I_PARENT_CODE" => 'PARENTS.CODE',
		'I_PARENT_NAME_RU' => 'PARENTS.NAME.NAME',
		'I_PARENT_TYPE_CODE' => 'PARENTS.TYPE.CODE',
		'I_PARENT_TYPE_NAME_RU' => 'PARENTS.TYPE.NAME.NAME'
	)
));
while($locationItem = $dbLocationItems->fetch())
{
	// ...
}

/*Array
(
    [I_PARENT_ID] => 24
    [I_PARENT_CODE] => 0000028023
    [I_PARENT_NAME_RU] => Россия
    [I_PARENT_TYPE_CODE] => COUNTRY
    [I_PARENT_TYPE_NAME_RU] => Страна
)
Array
(
    [I_PARENT_ID] => 58
    [I_PARENT_CODE] => 0000028056
    [I_PARENT_NAME_RU] => Ростовская область
    [I_PARENT_TYPE_CODE] => REGION
    [I_PARENT_TYPE_NAME_RU] => Область
)
Array
(
    [I_PARENT_ID] => 151167
    [I_PARENT_CODE] => 0000445112
    [I_PARENT_NAME_RU] => Ростов-на-Дону
    [I_PARENT_TYPE_CODE] => CITY
    [I_PARENT_TYPE_NAME_RU] => Город
)*/

Так же, для получения полной цепочки местоположения по ID можно использовать метод getPathToNode, а по коду местоположения метод getPathToNodeByCode:

$resLocation = \Bitrix\Sale\Location\LocationTable::getPathToNode(151167, [
	'select' => [
		'ID',
		'LNAME' => 'NAME.NAME',
		'SHORT_NAME' => 'NAME.SHORT_NAME',
	],
	'filter' => [
		'NAME.LANGUAGE_ID' => LANGUAGE_ID
	]
]);
if ($resLocation ) {
	$resLocation ->addReplacedAliases(array('LNAME' => 'NAME'));
	while($locationItem = $resLocation ->Fetch()) {
		$arLoc[] = $locationItem['NAME'];
	}
}
echo implode(', ', $arLoc);

//Россия, Ростовская область, Ростов-на-Дону

Для работы с избранными местоположениями обращаемся напрямую к базе данных:

$connection = Bitrix\Main\Application::getConnection();
$sqlHelper = $connection->getSqlHelper();
$sql = "SELECT LOCATION_CODE FROM b_sale_loc_def2site WHERE SITE_ID='".SITE_ID."' ORDER BY SORT";
$recordset = $connection->query($sql);
while ($record = $recordset->fetch())
{
    $arResultTmp[] = $record["LOCATION_CODE"];
}

Поиск местоположения можно осуществить с помощью метода \Bitrix\Sale\Location\Search\Finder::find(), и как сказанно в документации: "Параметры поиска, аналогичные параметрам LocationTable::getList(). Дополнительно используется ключ PHRASE – поисковая фраза". Но на данный момент это некорректное утверждение, так как фильтровать полученные результаты по типу местоположения не получится и в результате мы видим огромную портянку местоположений со всеми деревнями и областями:

$resLocation  = \Bitrix\Sale\Location\Search\Finder::find([
	'filter' => ['=NAME.LANGUAGE_ID' => "RU", '=TYPE.CODE' => 'CITY', 'PHRASE' => "Рост"],
	'select' => [
		'*',
		'ID' => 'ID',
		'NAME_RU' => 'NAME.NAME',
		'TYPE_CODE' => 'TYPE.CODE',
		'CODE' => 'CODE'
	]
],[
	'FALLBACK_TO_NOINDEX_ON_NOTFOUND' => true,
	'USE_INDEX' => true,//Использовать поисковый индекс
	'USE_ORM' => true
]);
while($locationItem  = $resLocation ->fetch())
{
	// ...
}

/*Array
(
    [ID] => 96631
    [CODE] => 0000273315
    [SORT] => 100
    [LT_SORT] => 100
    [NAME] => Ростов
    [LEFT_MARGIN] => 297700
    [RIGHT_MARGIN] => 297715
)
Array
(
    [ID] => 151167
    [CODE] => 0000445112
    [SORT] => 100
    [LT_SORT] => 100
    [NAME] => Ростов-на-Дону
    [LEFT_MARGIN] => 188545
    [RIGHT_MARGIN] => 188586
)
Array
(
    [ID] => 157266
    [CODE] => 0000503467
    [SORT] => 100
    [LT_SORT] => 200
    [NAME] => Роста село
    [LEFT_MARGIN] => 176310
    [RIGHT_MARGIN] => 176311
)
Array
(
    [ID] => 117826
    [CODE] => 0000337934
    [SORT] => 100
    [LT_SORT] => 200
    [NAME] => Ростани деревня
    [LEFT_MARGIN] => 255148
    [RIGHT_MARGIN] => 255149
)*/

Так же поиск местоположения можно осуществить через \Bitrix\Sale\Location\LocationTable::getList(). Тут мы можем отфильтровать по типу местоположений, чтобы исключить лишние:

$resLocation = \Bitrix\Sale\Location\LocationTable::getList(array(
    'filter' => [
		'=TYPE.CODE' => 'CITY', 
		'=NAME.LANGUAGE_ID' => LANGUAGE_ID, 
		'NAME_RU' => 'Рост%'
    ],
    'select' => [
		'*',
		'ID' => 'ID',
		'NAME_RU' => 'NAME.NAME',
		'TYPE_CODE' => 'TYPE.CODE',
    ]
));

while($locationItem = $resLocation->fetch()) {
    // ...
}

/*Array
(
    [ID] => 96631
    [CODE] => 0000273315
    [LEFT_MARGIN] => 297700
    [RIGHT_MARGIN] => 297715
    [DEPTH_LEVEL] => 4
    [SORT] => 100
    [PARENT_ID] => 96604
    [TYPE_ID] => 5
    [LATITUDE] => 0.000000
    [LONGITUDE] => 0.000000
    [COUNTRY_ID] => 24
    [REGION_ID] => 42
    [CITY_ID] => 96631
    [LOC_DEFAULT] => N
    [NAME_RU] => Ростов
    [TYPE_CODE] => CITY
)
Array
(
    [ID] => 151167
    [CODE] => 0000445112
    [LEFT_MARGIN] => 188545
    [RIGHT_MARGIN] => 188586
    [DEPTH_LEVEL] => 3
    [SORT] => 100
    [PARENT_ID] => 58
    [TYPE_ID] => 5
    [LATITUDE] => 0.000000
    [LONGITUDE] => 0.000000
    [COUNTRY_ID] => 24
    [REGION_ID] => 58
    [CITY_ID] => 151167
    [LOC_DEFAULT] => N
    [NAME_RU] => Ростов-на-Дону
    [TYPE_CODE] => CITY
)*/