• PHP + 1C интеграция. Что почитать?

    mrspender
    @mrspender
    Мое мнение — они все сделали так, чтобы в этом либо никто не разобрался, либо единицы, потратив кучу времени на гадание на кофейной гуще.

    Все-таки продажи 1С-Битрикс куда важнее, чем дела программистов-конкурентов.
    Ответ написан
    Комментировать
  • Как в Битриксе отключить авторизацию для внешних запросов на роуты (routing_index.php)?

    @titkov96
    в файле \bitrix\access.php нужно дать права на файл \bitrix\routing_index.php
    Ответ написан
    Комментировать
  • Как правильно работать с сторонним api?

    @Flying
    Конечно контроллер - не место для подобных действий.

    Как правильно указал Владимир Коротенко - перенос кода, отвечающего за работу с внешним API в отдельный сервис - это первое что вам нужно сделать. Это действие открывает для вас массу возможностей: подмена сервиса для разных сценариев, использование заглушек для тестов, вызовы вне контроллеров и т.д. Кроме того сам код при этом становится более простым и поддерживаемым, а также лучше соответствует принципам SOLID.

    Если после выделения сервиса вы поймёте что для вас необходима возможность изменения его реализации - важно выделить ключевые методы в интерфейс и использовать именно интерфейс для внедрения зависимостей в те же контроллеры.

    Для реализации самих запросов внутри сервиса логично использовать Symfony HTTP Client.

    После этого у вас возможны различные сценарии в зависимости от того что же этот API делает.

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

    Если вы забираете из API данные для подготовки своего ответа, но сами эти данные меняются не постоянно - логично будет добавить в ваш сервис поддержку кэширования с использованием Symfony Cache.

    Если вы забираете данные из API или отправляете данные туда, но они не зависят от контекста текущего запроса - этот процесс логичнее всего вынести в консольную команду, реализованную через Symfony Console и дёргать её по cron'у.

    Альтернативно, если вы используете Symfony 4.4 или 5.x - вы можете организовать этот процесс через новый Symfony Messenger. Он же будет лучшим вариантом если, к примеру, запросов много или они тяжёлые и вам нужно организовать их распределение.
    Ответ написан
    Комментировать
  • Не отправляются файлы на сервер через BX.ajax.runComponentAction, в чем может быть проблема?

    Starina_js
    @Starina_js
    full-stack web dev
    Эту ветку смотрели?

    BX.ajax.runComponentAction('componentName', "actionName", {
        mode: 'ajax',
        data: new FormData(form)
    })


    use \Bitrix\Main\Application;
    $request = Application::getInstance()->getContext()->getRequest();
    $files = $request->getFileList()->toArray();
    Ответ написан
    4 комментария
  • PHP - как оставить только 2 знака(не округлить) после запятой?

    На сегодня единственный разумный вариант:

    bcdiv('12.345', 1, 2); // 12.34
    Ответ написан
    3 комментария
  • Как в Битриксе отключить авторизацию для внешних запросов на роуты (routing_index.php)?

    @PetrPo
    prolog_before.php не требует авторизаию.

    Авторизацию требует controller (так по умолчанию сделано), в нем должен быть метод configureActions, в котором отменяешь необходимость авторизации

    public function configureActions()
    {
      return [
        'addBook' => [
          'prefilters' => [
    
          ],
          '-prefilters' => [
            \Bitrix\Main\Engine\ActionFilter\Authentication::class
          ],
        ]
      ];
    }


    P.S.
    addBook = ...function addBookAction()
    Ответ написан
  • Как импортировать в Битрикс24 пользователей и структуру из 1С?

    gromdron
    @gromdron Куратор тега Битрикс24
    Работаю с Bitrix24
    Да, в Битрикс24 есть возможность импорта орг.структуры и пользователей из 1С, есть даже связывание этих пользователей по логину с конкретным заведенным доменом, однако на практике штатные инструменты для группы компаний не подходят. Подобные работы выполняются под ключ для каждой компании партнерами-интеграторами.
    От себя могу добавить следующее:
    1. Если хотите чтобы проблем не было, то поставщиком пользователей (профилей) и орг.структуры должна являться 1С. И это должна быть именно одна система, потому как несколько подобных систем-источников вызывают коллапс в Б24.
    2. Если хотите использовать несколько доменов AD, то оставьте только минимальный набор полей - флаг активности, логин. AD должен выступать исключительно в роли авторизационного сервера, поэтому никакого обмена с периодичностью, построения орг.структуры и создания пользователей на портале. Только активность и привязка к группам.
    3. Для привязки заранее создайте как минимум 3 группы в каждом AD: "bitrix users", куда включите всех пользователей которые должны маппится в группу сотрудников, "bitrix admins" это те пользователи из числа "bitrix users", кто должны стать админами на портале и "bitrix ignored" (учетки которые будут игнорироваться).
    - Если пользователь должен стать админом - в группы "bitrix users" и "bitrix admins" его.
    - Если учетку не нужно затягивать в Б24 то прописываем в "bitrix ignored" и соответственно ее в исключения. Помните если пользователь будет одновременно в группе ignored и users, то на портал он не попадет.

    По-поводу SSO на мультидоменные структуры (именно чтобы открыть портал и сразу авторизован) это не просто.
    Либо нужно сломать BitrixVM подключив Kerberos, либо нужно пилить свой модуль для какого-нибудь KeyCloak/ADFS или другого поставщика авторизации. Штатный NTLMv2 работает только с одним доменом (тем в который введен сервер).
    Ответ написан
    Комментировать
  • Как правильно именовать таблицы, столбцы в базе данных?

    JohnnyGat
    @JohnnyGat
    Стараюсь писать код, понятный человеку.
    SQL Style Guide - www.sqlstyle.guide
    Перевод на русский - www.sqlstyle.guide/ru
    Ответ написан
    6 комментариев
  • Как получить ID формы в которой находится кнопка?

    FLUNKEY
    @FLUNKEY
    самовар
    Я думаю прежде чем задавать такие вопросы, лучше прочитать ту же документацию по jQuery или на край загуглить.

    $('form button').click(function(){
        var $form = $(this).parents('form');
        var id = $form.attr('id');
    });
    Ответ написан
    Комментировать
  • Почему Service Locator это зло и что использовать вместо?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Все эти страшные слова - они на самом деле всегда про одно и то же - про связность. Когда ты хардкодишь внутри класса вызов какого-то конкретного сервиса - ты намертво к нему привязываешься. И чтобы поменять сервис на другой, ты будешь вынужден поменять код класса. Окей, поменял. И тут же в другом месте, где этот же класс использовался, что-то сломалось! И что теперь? Делать два класса, которые различаются одной строчкой? Нет конечно. А как тогда использовать один и тот же класс для обработки разных входящих данных (или одних и тех же данных, но разными способами)? Сделать его поведение изменяемым. То есть сделать изменяемыми те инструменты, которыми он пользуется - т.е. его зависимости.

    Поэтому все зависимости обычно передаются через конструктор (и поэтому и называются инъекция зависимостей.)

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

    Но тут надо понимать, что всё это работает только при правильном применении ООП. А точнее просто при применении ООП. Потому что 98% "ООП" кода, который пишется на РНР - это голимая процедурщина, даже если она обёрнута в классы и методы. Если у тебя метод класса представляет из себя стену кода, которую ты тупо перенёс из файла, инклюдившегося в любимое похапешное спагетти - то это не ООП. Это та же процедурщина, вид сбоку. И смысл использования dependency injection ты с ним не почуствуешь. Будешь конечно применять, но в качестве карго культа - потому что тебе это на тостере написали.
    А вот когда твой код начнет становиться действительно объектным - тогда стразу станет понятнее.


    Похожим на сервис локатор является сервис- или DI-контейнер. Используемый вручную, он является тем же самым сервис локатором. Поэтому вручную его никогда не надо вызывать - что и запрещается в симфоневских конроллерах - а только для автоматического создания классов. В МВЦ у тебя ведь очень многие объекты создаются автоматом - сущности, контроллеры. И вот для того, чтобы при автоматическом создании экземпляра класса у тебя были на руках все требуемые сервисы - и нужен контейнер.

    Соотвтственно, ответ на вопрос "что использовать?" очень простой:
    - при ручном создании экземпляра объекта, все зависимости передавать в него через конструктор, а не получать "из воздуха" в коде.
    - при автоматическом создании экземпляра объекта, использовать dependency injection container

    В этим смысле очень полезно освоить Симфони - строгий фрейворк, в котором нет сервис локатора и в котором запрещено пользоваться контейнером напрямую.
    Ответ написан
    4 комментария
  • Кодировка базы данных для русскоязычного сайта Laravel?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Господи, ну нельзя же настолько буквально воспринимать вопросы.
    Ну неужели из контекста непонятно, что автор спрашивает про кодировку, а не про набор правил сравнения?

    Автор, кодировка, которая тебе нужна, называется utf8mb4. Вот её и ставь.
    А набор правил сравнения подставится автоматически, и в целом без разницы, какой - utf8mb4_general_ci или utf8mb4_unicode_ci
    Ответ написан
    Комментировать
  • Где находится в коде этот счётчик (коробочная версия)?

    gromdron
    @gromdron Куратор тега Битрикс24
    Работаю с Bitrix24
    Перед началом: да, можно вывести счетчик, но если вы хотите сделать обновление данных через push-сервер нужно немного модифицировать шаблон меню.
    И под счетчиками, я понимаю стандартный механизм использующий API: CUserCounter (таблица b_user_counter)

    Чтобы вывести цифру нужно сделать следующее: при описании меню (.left.menu.php) в 3-й параметр пункта нужно добавить параметр counter_num.
    Array(
    	'Test menu',
    	"/test", 
    	Array(), 
    	Array(
    		'counter_num' => 7,
    	), 
    	"" 
    ),


    В данном случае 7 - цифра, которая будет отображаться около номера.
    Сам же счетчик можно наполнять данными откуда угодно.

    Однако если вы хотите добавить обновляемый через push-сервер счетчик то нужно добавить еще один параметр counter_id (это идентификатор стандартного счетчика битрикса):
    Array(
    	'Test menu',
    	"/test", 
    	Array(), 
    	Array(
    		"counter_id" => "test-counter-menu",
    		'counter_num' => 7,
    	), 
    	"" 
    ),


    Далее, в шаблоне компонента меню (/bitrix/templates/bitrix24/components/bitrix/menu/top_horizontal/template.php) нужно перед кодом:
    $items[] = $newItem;

    добавить:
    if ( isset($item["PARAMS"]["counter_id"]) )
    {
    	$newItem['COUNTER_ID'] = $item["PARAMS"]["counter_id"];
    }


    Теперь когда вы будете обновлять счетчик, он будет автоматически обновляться у пользователей.
    Ответ написан
    1 комментарий
  • Какой выбрать локальный сервер?

    kentuck1213
    @kentuck1213
    Не надо на подобие денвера.
    open-server.ru
    Ответ написан
    Комментировать
  • Какой выбрать локальный сервер?

    Enapiuz
    @Enapiuz
    велосипедостроительное бюро
    На винде сам пользуюсь и всегда всем советую OpenServer. Наверное самая безгеморройная вещь. Главное запускать с правами админа, чтобы hosts правился автоматически.
    Ответ написан
    Комментировать
  • Какой выбрать локальный сервер?

    muhammad_97
    @muhammad_97
    PHP-разработчик
    OpenServer или XAMPP
    Ответ написан
    Комментировать
  • Как добавить запись в историю заказа?

    @ArmBar
    \Bitrix\Main\Loader::includeModule('sale');
    $historyEntityType = 'ORDER'; //В данном случае для заказа
    $historyType = 'ORDER_COMMENTED'; //Нужный тип можно посмотеть в классе \CSaleOrderChangeFormat в $operationTypes
    $order = \Bitrix\Sale\Order::load($orderId);
    \Bitrix\Sale\OrderHistory::addAction(
    			$historyEntityType,
    			$order->getId(),
    			$historyType,
    			$order->getId(),
    			$order,
    			['COMMENTS' => 'Новый комментарий']
    );
    $order->save();
    Ответ написан
    Комментировать
  • Как проверять на существование лидов с таким же Email. Битрикс24. Коробочная версия?

    @elov4anin Автор вопроса
    Frontend developer
    Добавлю так же решение которые по советовали в ТП Битрикса и которе применил в итоге

    CModule::IncludeModule('crm');
    $rs = CCrmFieldMulti::GetList(
       array(),
       array(
          'ENTITY_ID' => 'LEAD', // выбираем только email лида
          "VALUE" => "test@mail.ru",
          //"@ELEMENT_ID" => array(1,2), // ID выбираемых лидов
          //"TYPE_ID" => "EMAIL",
          'COMPLEX_ID' => 'EMAIL_WORK' // тип email: "Рабочий"
       )
    );
    while($ar = $rs->Fetch()) 
    {
       echo '<pre>';
       print_r($ar);
       echo '</pre>';
    }
    Ответ написан
    Комментировать
  • Как сделать ожидание выполнения функции в JavaScript?

    @vshvydky
    Если функция с колбеком надо обернуть ее в промис, чтобы работать с промисами синхронно, нужно либо использовать рекурсивный вызов промисов один за другим, либо в цикле фор но в асинк функции с прерываниями на авайт
    Ответ написан
    Комментировать
  • Человекопонятные даты в js на русском языке?

    DenZzeuro
    @DenZzeuro
    Мотоциклы, кофе
    new Date().toLocaleString('ru', {
    			  year: 'numeric',
    			  month: 'long',
    			  day: 'numeric'
    			});
    Ответ написан
    2 комментария
  • Как опубликовать сообщение в группе с помощью API?

    gromdron
    @gromdron Куратор тега Битрикс24
    Работаю с Bitrix24
    Чтобы отправить сообщение в живую ленту нужно еще более изощренный метод.

    Подключаем модуль Соц.сети:
    CModule::IncludeModule("socialnetwork");

    Чтобы отправить сообщение в ленту, нужно чтобы существовал пост, который будет отправлен в ленту, поэтому создаем сначала пост:

    $arFields = array(
     "TITLE" => "Заголовок записи",
     "DETAIL_TEXT" => "Тело сообщения",
     "BLOG_ID" => 1, //ID отправителя
     "AUTHOR_ID" => 1, //ID блога, в котором будет запись
     "DATE_PUBLISH" => '11.02.2014 09:08', // дада
     "PUBLISH_STATUS" => BLOG_PUBLISH_STATUS_PUBLISH, // Читаем в API
     "ENABLE_TRACKBACK" => 'N',
     "ENABLE_COMMENTS" => 'Y'
    );


    При успешном добавлении ($ID = CBlogPost::Add($arFields);) получим ID blogPost записи

    Затем необходимо отправить это сообщение в ленту, для нам нужен фрагмент кода (заменить соответствующим образом):

    $arEvent = array (
    	'EVENT_ID'     => 'blog_post',
    	'=LOG_DATE'    => 'now()',
    	'TITLE_TEMPLATE' => '#USER_NAME# добавил(а) сообщение "#TITLE#" в блог',
    	'TITLE'    => "Заголовок записи",
    	'MESSAGE'  => "Текст записи",
    	'TEXT_MESSAGE'  => "Текст записи",
    	'MODULE_ID'     => 'blog',
    	'CALLBACK_FUNC' => false,
    	'SOURCE_ID'     => $ID,
    	'ENABLE_COMMENTS'  => 'Y',
    	'RATING_TYPE_ID'   => 'BLOG_POST',
    	'RATING_ENTITY_ID' => $newID,
    	'ENTITY_TYPE' => 'U',
    	'ENTITY_ID'   => '1',
    	'USER_ID'     => '1',
    	'URL' => '/company/personal/user/1/blog/'.$ID.'/',
    );


    Создаём запись в ленте через: CSocNetLog::Add, на выходе получаем eventID (в случае успеха)

    Если все прошло хорошо, то выставляем права на пост (в премере отправляем ВСЕМ ПОЛЬЗОВАТЕЛЯМ G3)

    // Выдает права
    CSocNetLogRights::Add ( $eventID, array ("G3") );
    // Отправляет уведомление о новом сообщении
    CSocNetLog::SendEvent ( $eventID, 'SONET_NEW_EVENT' );


    Радуемся =)

    Все параметры получаются по средствам GetList например.
    Ответ написан
    4 комментария