Задать вопрос
  • Какой способ получения IP лучше?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Ну хз, на мой взгляд это не равноценные примеры: субьективно читать первый не проще, я бы отдал предпочтение функции get_ip(), с другой стороны второй пример не делает того же, что делает первый (например валидацию не проводит).

    /**
     * Return client ip if find, or null
     * @return string|null
     */
    function getUserIp()
    {
        static $ip;
    
        if ( !is_null($ip) )
        {
            return $ip;
        }
    
        $candidates = [
            @$_SERVER['HTTP_CLIENT_IP'],
            @$_SERVER['HTTP_X_FORWARDED_FOR'],
            @$_SERVER['REMOTE_ADDR']
        ];
    
        foreach ($candidates as $candidate)
        {
            if ( \filter_var($candidate, \FILTER_VALIDATE_IP) )
            {
                $ip = $candidate;
                break;
            }
        }
    
        return $ip;
    }
    
    var_dump(getUserIp());
    Ответ написан
    Комментировать
  • Почему детальная страница периодически ломается?

    gromdron
    @gromdron
    Работаю с Bitrix24
    При первом осмотре в глаза бросается система кеширования и плохо настроенная многосайтовость.

    На эталонной странице (где все норм. отображается) есть вызов к spead'у сайта error440.ru
    При этом если сравнить эталонную страницу и ту же страницу, но с непрогруженными данными получается что не грузится бОльшая часть контента контент. Я нашел расхождение в 40+ строчках.
    То есть один из компонентов (который собственно показывает карточку) не прогружается.
    Ответ написан
  • Как добавить в JOIN подзапрос?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Насколько мне известно, подобный запрос в 1 в битриксе не завернуть (минимум 2 независимых запроса).
    Дело в том, что Битрикс работает с entities, и у него нет queryBuilder'а, соответственно он может строить запросы только к известным сущностям.
    А далее начинается пляска, потому как часть запроса с IFNULL является ExpressionField, а join является ReferenceField и выражение expression нельзя применить для результата reference.

    У Вас будет ошибка:
    Expected ScalarField or ExpressionField in `*` build_from, but `Bitrix\Main\Entity\ReferenceField:*` was given. (0)
    Ответ написан
  • Как правильно собрать статистику кликов по ссылке?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Как по мне - так решение с +1 в элементе и ajax отправка не лучшая идея.
    Я бы подключил какую-нибудь Яндекс.Метрику, настроил цель на нажатие ссылки и получал бы через API в админке отчеты. Если очень уж принципиально хранить у себя, то можно раз в сутки забирать информацию.
    Ответ написан
    Комментировать
  • Как интегрировать в Битрикс 24 Открытые линии сторонний месенджер?

    gromdron
    @gromdron Куратор тега Битрикс24
    Работаю с Bitrix24
    1) Придумываем коннектору уникальный slug
    2) На примере imconnector.baseconnector разарбатываем собственный компонент коннектора
    3) В \Bitrix\ImConnector\CustomConnectors смотри события на вызовы кастомного коннектора и что именно они должны вернуть

    Документации по этому счастью особо нет (пока, но не известно будет ли), поэтому ковыряние :(
    Ответ написан
    Комментировать
  • Как получить все разделы инфоблока, с подразделами всех уровней вложенности?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Перечитал и вообще не понял вопроса. Есть же стандартный CIblockSection::GetList() который за 1 запрос прекрасно все достает и со вложенностью.

    В спойлере указал код, который получить все разделы включая подразделы для конкретного инфоблока, отсортированные по левому отступу (т.е. сверху вниз, слева на право). И все это за 1 запрос к БД средствами API.

    Пример который проверял
    /**
     * Всегда считаем что модуль установлен, 
     * поэтому просто подключаем его
     */
    \Bitrix\Main\Loader::IncludeModule('iblock');
    
    /**
     * У меня для тестирования инфоблок с номером 5,
     * у тебя может быть любой другой инфобло
     * 
     * @var array Параметры фильтрации
     */
    $arFilter = [
    	'IBLOCK_ID' => 5
    ];
    
    /**
     * В Битриксе разделы хранятся по принципу Nested sets
     * 
     * @var array Параметры сортировки
     */
    $arOrder = [
    	'LEFT_MARGIN' => 'ASC'
    ];
    
    /**
     * @var array Поля разделов
     */
    $arSelect = [
    	'ID',
    	'LEFT_MARGIN',
    	'DEPTH_LEVEL',
    	'NAME'
    ];
    
    $resSections = \CIBlockSection::GetList($arOrder, $arFilter, false, $arSelect);
    
    while( $arSection = $resSections->fetch() )
    {
    	var_dump($arSection);
    }


    В чем я ошибся и где я делаю не так?
    Ответ написан
    1 комментарий
  • Как сделать добавление товаров в корзину только из одной родительской категории?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Давай поговорим немножко о другом.
    Предположим, что у тебя следующая структура:

    Москва (id: 1)
    Приборы (id: 2)
    Инструменты (id: 5)
    Санкт-Петербург (id: 3)
    Инструменты (id: 4)

    Если товар принадлежит к категории 5, то он точно из Москвы и соответственно при добавлении товара из id:2 он должен добавиться.
    А если товар у тебя есть одновременно и там и там? Ну скажем, товар был добавлен и в id:4 и в id:5 - ситуация может быть и такой. В твоем коде, если товар так был занесен, то при добавлении родительский раздел может быть как СПБ, так и Москва, тогда в одном из городов твоя логика работать не будет, а это неправильно.

    Я тут набросал пару примеров и сделал пару допущений:
    1) Какой-то товар уже в корзине
    2) Ты уже знаешь ID города, товар из которого добавлен в корзину

    Весь код (без магии), отвечающий за проверку возможности добавлять товар:
    /**
     * @var integer Идентификатор товара из CITY_PRODUCTS_IBLOCK_ID, добавляемого в корзину
     */
    $iProductId = 650;
    
    /**
     * @var integer Идентификатор города, товар которого уже добавлен в корзину
     */
    $iCityId = 91;
    
    if ( canAddByCity($iProductId, $iCityId) )
    {
    	echo "Можно добавить";
    }
    else
    {
    	echo "Нельзя добавить";
    }


    Как видишь, в этом коде нет ничего интересного. Вся магия начинается в функции canAddByCity (да-да, написано не оптимально, нужно оптимизировать и т.п. и т.д. но для пояснения сойдет):

    /**
     * @var int Уровень вложенности, где находятся города (у меня 2)
     */
    define('CITY_DEPTH_LEVEL', 2);
    
    /**
     * @var integer Идентификатор инфоблока, где ищем товары
     */
    define('CITY_PRODUCTS_IBLOCK_ID', 5);
    
    /**
     * Возвращает true, если товар $product можно добавить в корзину
     * @param integer $product 
     * @param integer $city 
     * @return boolean
     */
    function canAddByCity( $product, $city = 0 )
    {
    	if ( empty($city) )
    	{
    		return true;
    	}
    
    	if ( !\Bitrix\Main\Loader::IncludeModule('iblock') )
    	{
    		return false;
    	}
    
    	/**
    	 * @var array Список категорий верхнего уровня для сравнения
    	 */
    	$arRootGroups = [];
    
    	/**
    	 * @var CDBResult
    	 * @see https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblockelement/getelementgroups.php
    	 */
    	$resGroups = \CIBlockElement::GetElementGroups($product, true);
    
    	while( $arGroup = $resGroups->fetch() )
    	{
    		/**
    		 * А вдруг товар без категории и сразу добавлен в город
    		 * т.е. без привязки?
    		 */
    		if ( $arGroup['DEPTH_LEVEL'] == \CITY_DEPTH_LEVEL )
    		{
    			$arRootGroups[] = $arGroup['ID'];
    			continue;
    		}
    
    		/**
    		 * @todo Запросы в цикле это очень плохо. 
    		 * Лучше запомнить где-то разделы и лишние уровни и дополнительным
    		 * циклом пройтись после - запросов будет меньше и будет быстрее работать
    		 */
    		$iRootSectionId = getSectionIdByDepthLevel($arGroup['ID']);
    
    		if ( !empty($iRootSectionId) )
    		{
    			$arRootGroups[] = $iRootSectionId;
    			continue;
    		}
    	}
    
    	// Какие корневые группы имеет этот товар
    	// можно посмотреть через код
    	//var_dump($arRootGroups);
    
    	return in_array($city, $arRootGroups);
    
    }
    
    /**
     * Возвращает код родительского раздела $section из инфоблока $iblockId
     * на уровне CITY_DEPTH_LEVEL. В случае отсутствия возвращает 0
     * @param integer $section 
     * @param integer $iblockId 
     * @return integer
     */
    function getSectionIdByDepthLevel( $section, $iblockId = \CITY_PRODUCTS_IBLOCK_ID )
    {
    	$section = intval($section);
    
    	if ( empty($section) )
    	{
    		return 0;
    	}
    
    	if ( empty($iblockId) )
    	{
    		return 0;
    	}
    
    	if ( !\Bitrix\Main\Loader::IncludeModule('iblock') )
    	{
    		return 0;
    	}
    
    	$resChain = \CIBlockSection::GetNavChain($iblockId, $section, ['ID','DEPTH_LEVEL','IBLOCK_SECTION_ID']); 
    
    	while( $arSection = $resChain->fetch() )
    	{
    		if ( $arSection['DEPTH_LEVEL'] == \CITY_DEPTH_LEVEL)
    		{
    			return $arSection['ID'];
    		}
    	}
    
    	return 0;
    }
    Ответ написан
    Комментировать
  • Битрикс для организаций обязаловка?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Добрый день Станислав,

    Нет, Ваше утверждение в корне неверно. Никто не обязывает государственные и мунициапальные учреджения покупать именно битрикс, требования к закупке программных обеспечений для гос.предприятий регламентируются самими предприятиями.

    Тут играет роль 2 фактора:

    1) Все это должно пройти через тендеры. Ну не вот прямо все, но бОльшая часть уж точно проходит именно через тендеры. И именно тут и отваливается большинство систем - в noname системах непонятно сколько можно отпилить и где отжать, а вот с простыми системами типа Битрикса очевидно.
    К тому же, важную роль играют именно баллы, которые выдаются за все подряд - сайты на такой же платформе, работ подрядчика с такими же гос. учреждениями, профильные специалисты (т.е. те, что можно подтвердить дипломами и т.п.). Я уж не говорю о том, кто это в итоге будет обслуживать, потому что непонятно как это будет создаваться.

    2) А далее уже встает вопрос в маркетинге - битрикс очень хорошо распиарен и на нем сделано уж очень много сайтов, в том числе и для гос. учреждений.
    Вот посудите сами: Вы ген.директор МосГорЧтоТоТам и Вам нужен сайт. Какую компанию при прочих равных (для упрощения считаем так) вы выберете:
    - Богатырь, с портфолиом: МинЮст, МинСтрой, МинКомСвязь, МинСельХоз, ФАС, МинОбрНауки.
    - Иванушка, с портфолиом: Интернет-магазин Мёда, Личный сайт Пети Петина и т.п.

    Конечно Вы будете работать с Богатырем, поскольку они уже знают специфику работы с гос. учреждениями, имеют опыт и т.п.
    Ответ написан
  • Как сделать нотификацию о новых сообщения?

    gromdron
    @gromdron
    Работаю с Bitrix24
    В редакция Эксперт, Малый Бизнес и Бизнес есть модуль Push'n'pull

    Модуль Push and Pull позволяет организовать транспорт для отправки мгновенных команд. Реализация данного функционала в виде отдельного модуля позволяет любому другому модулю (в том числе и модулям сторонних разработчиков) используя API отправлять мгновенные нотификации и сообщения клиентам.
    Ответ написан
    Комментировать
  • Как правильно сделать фильтр со сложной логикой?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Скорее всего такую логику Битрикс уже не осилит и Вам нужно обращаться в SQL и формировать уже прямой запрос в БД. Либо, можно сделать промежуточную таблицу/инфоблок/хайлоадблок и уже искать там.
    Ответ написан
    Комментировать
  • Как генерировать orders.xml в битриксе?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Я выяснил, что файл orders.xml генерируется только при запросе со стороны 1С.

    Файл не генерируется при запросе, он формируется в 1С и отправляется в Битрикс.
    Алгоритм выгрузки данных на сайт указан в документации.
    Дополнительно можно почитать, например и у Дениса
    Можно ли самостоятельно создавать этот файл в какой-либо директории сайта?

    Самостоятельно создать можно, но для загрузки необходимо вручную пройти по шагам импорта.
    По крайней мере первые 3 шага пройти придется, а дальше вручную можно положить файл в /upload/1c_exchange/ (ну или в зависимости от того что загружаете)
    Ответ написан
    7 комментариев
  • Как из двух массивов сделать один двумерный массив?

    gromdron
    @gromdron
    Работаю с Bitrix24
    В Вашем случае есть 2 ограничения:
    1) Если у Вас будет 2 пользователя с одинаковым именем, то их данные смешаются в одну кучу
    2) Если немного изменить формат $users то будет значительно проще получить результирующий массив (не нужен будет первый цикл на ассоциативность)

    /**
     * Шаг 1 - разворачиваем $users в плоский массив
     * Если есть возможность получить его сразу ассоциативным,
     * то это было бы лучше
     */
    $usersAssoc = [];
    
    foreach ($users as $user)
    {
    	$usersAssoc[ $user['id'] ] = $user['name'];
    }
    
    /**
     * Шаг 2 - выполяем группирующее преобразование наших $punch
     */
    $result = [];
    
    foreach ($punch as $time)
    {
    	if ( !array_key_exists($time['user_id'], $usersAssoc) )
    	{
    		// В punch есть массив, который относится к пользователю
    		// о окотором мы не знаем
    		continue;
    	}
    
    	$result[ $usersAssoc[ $time['user_id'] ] ][ $time['id'] ] = $time;
    }
    
    
    echo "<pre>";
    var_dump($result);
    echo "</pre>";
    Ответ написан
  • Кто-то видел Blueprint Interface для php?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Эм.. а какой кейс это закроет?
    А UE насколько я знаю, это заменяет все - и подход стандартизирован и действия и взаимоотношения.
    В вебе нет такой проблемы - классы обычно запиливаются для конкретного ORM/DataMapper и где-то, даже есть свой скаффолдинг.
    Ответ написан
  • Почему трёхуровневая архитектура клиент-серверного приложения надёжней двухуровневой?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Эм... а почему в теме вопроса один вопрос, а в тексте другой? Это фишка такая спрашивать 2 разные вещи в одном вопросе?
    Какая архитектура быстрее трёхуровневая или двухуровневая?

    С точки зрения пользователя или разработчика?
    В частном случае, при использовании масштабирования, трехуровневая структура будет быстрее для пользователя, за счет распределения нагрузки.
    Почему трёхуровневая архитектура клиент-серверного приложения надёжней двухуровневой?

    Я процитирую многоуважаемого sim3x
    Кто сказал, что надежнее?
    Ответ написан
    Комментировать
  • На чем основывается логика ERP систем?

    gromdron
    @gromdron
    Работаю с Bitrix24
    На мой взгляд, у Вас происходит путанница двух слабосвязанных возможностей системы.

    С одной стороны, Вы говорите о НСИ (насколько я понимаю Нормативно-справочная информация), а с другой стороны о так называемом RBAC (role based access control).
    Разложить можно следующим образом:
    1) Есть пользователи, который с определенной стороны являются справочником, а с другой стороны предметом иденктификации пользователя в системе
    2) Есть роль, которая складывается из совокупоности возможных действий в системе.
    3) Пользователь может иметь несколько ролей и права пользователя считаются исходя из совокупонсти максимально доступных прав.

    Причем возможные действия системы это не полностью динамический справочник, т.е. есть те вещи, которые оттуда не удаляются.

    Приведу пример: есть у нас некая ERP в которой 300 сотрудников и 3 роли - "гость" (по факту может не существовать в системе), "сотрудник", "администратор".
    Если мы всех 300 пользователей привяжем к роли "Сотрудник", а потом попытаемся ее удалить, то тут может быть несколько вариантов решения данной ситуации (разные системы применяют разные методы)

    С точки зрения удаления роли:
    - Роль не удаляется, пока есть хотя бы один сотрудник с такой ролью
    - Роль помечается удаленной и она больше не учитывается в наборе прав, но отображается в системе
    - Роль удаляется, только если пользователь отметил в какую роль добавить существующих пользователей
    - Роль просто удаляется, оставляя систему в состоянии "сломанной целостности".

    Что касается вопроса про справочники, то в общем понимании слова под этим подразуемевается в основном пользовательская информации справочного (внезапно!) характера. Т.е. эта информация не влияет на технический аспект работы системы, но напрямую завязана на бизнес-логику системы (все можно оспорить конечно же).
    Например справочником может служить:
    - Тип формы собственности (Государственная, Муниципальная, Частная и т.п.)
    - Организационно-правовая форма (Товарищество, Общество, Акционерное общество и т.п.)
    - Сфера интересов (IT, Сельское хозяйство и т.п.)

    То есть любая информация представленная в виде списка.
    P.S. В частном случае и пользователи и роли тоже являются справочниками.
    Ответ написан
    9 комментариев
  • Как убрать редирект восстановленной копии bitrix на боевой сайт?

    gromdron
    @gromdron
    Работаю с Bitrix24
    1) Произведите очистку кеша. В 90% случаев это решает проблему.
    Если доступ в админ панель не работает, удалите содержимое папок /bitrix/managed_cache/, /bitrix/cache/ и /bitrix/stack_cache/ вручную.

    2) Проверьте настройки проактивной защиты - если на боевом сайте она включена.
    Для этого придется подключиться к СУБД и вручную произвести зачистку данных модуля (радикально, но работает).
    Ответ написан
  • Как разобрать строку в XSLT преобразовании?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Реализовать подобное можно при помощи substring.

    XML-документ:
    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-stylesheet type="text/xsl" href="docstyle.xsl"?>
    
    <Документы>
        <Документ КНД='1102345' ДатаДок="16.01.2012" КодНО="7601" />
        <Документ КНД='1111053' ДатаДок="12.12.2016" КодНО="7601" />
    </Документы>


    XSL-схема (docstyle.xsl)
    <?xml version="1.0" encoding="UTF-8" ?>
    
    <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns="http://www.w3.org/1999/xhtml">
        <xsl:output method="xml" indent="yes" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>
    
        <xsl:template match="Документы/Документ">
            <tr>
                <td><xsl:value-of select="@ДатаДок"/></td>
                <td><xsl:value-of select='substring(@КНД,1,1)'/></td>
                <td><xsl:value-of select='substring(@КНД,2,1)'/></td>
                <td><xsl:value-of select='substring(@КНД,3,1)'/></td>
                <td><xsl:value-of select='substring(@КНД,4,1)'/></td>
                <td><xsl:value-of select='substring(@КНД,5,1)'/></td>
                <td><xsl:value-of select='substring(@КНД,6,1)'/></td>
            </tr>
        </xsl:template>
    </xsl:stylesheet>
    Ответ написан
    Комментировать
  • Как указать условия доставки в карточке товара Битрикс?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Да как всегда способов масса :)

    Начнем с самого простого, нудного и заведомо гиблого пути - указание текста доставки напрямую в описании товара.
    Плохой вариант, едем дальше.

    Можно создать инфоблок-справочник с типами товара. У самого товара делать привязку к инфоблоку и выводить в шаблоне карточки товара.
    Хороший вариант - быстрый в реализации, совсем не геморройный.
    Однако есть ньанс - он совсем не связан с службами доставки. То есть, если в инфоблоке Вы напишете - 1-2 дня, а в Службе доставки 5-6, то на странице оформления заказа он увидит 5-6 дней, а не 1-2.

    Еще более лучшим решением, является создание ограничений на службу доставки, получение и их обработка на странице товара и уже вывод пользователю.
    Однако это очень долгий и трудный путь.

    Наилучшей комбинацией было бы создание своего ограничения в службе доставки завязанного на инфоблок-справочник. Т.е. комбинация 2 и 3 решения.

    P.S. Как прицел на будущее я бы рекомендовал последний вариант, однако ввиду начинающего знакомства с Битриксом только 2 вариант.
    Ответ написан
    Комментировать
  • Как в метатеги вставить переменную в битриксе?

    gromdron
    @gromdron
    Работаю с Bitrix24
    А эти варианты особо и не будут работать.
    Можете попробовать универсальный синтаксис конечно, но не думаю что в этой части он работает.
    $APPLICATION->SetPageProperty("title", "={$cur_city[$poddomen]}");


    Что касается именно задачи, то обычно это делается так:
    1) Разрабатываем компонент, ну например custo:header.meta
    2) В компоненте проверяем условия (например через GetPageProperty), а так же доп. параметры.
    Если по всем показателям нужно заменить - используйте конструкцию Lorem Ipsum . Если заменять не нужно - пропускаете.

    Важный вопрос: Почему делать нужно именно так?
    В Битрикс24 нельзя лишать пользователя возможности переопределять конкретные теги на страницах.
    Лучше это все делать в одном месте, чем потом искать откуда появляется $cur_city и что такое $poddomen.
    Да и к тому, же, нужно будет проходиться по каждой странице и смотреть что нет ошибок ли на других, а так - 1 компонент который целостно закрывает эту задачу.
    Ответ написан
    Комментировать
  • Битрикс. Почему ломается верстка после выхода из логина?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Все как всегда: все было хорошо, как вдруг стала ломаться верстка после разлогинивания.


    Компонент выводит данные из инфоблока? Права проверяли?
    Ответ написан