Для выполнения каких-либо действий в назначенный момент в Битриксе используются агенты: учебный курс и cправка API.
Агенты названы крайне неудачно "периодические" и "непериодические". Разберём, какие реально бывают агенты.
Агент - это запись в специальной таблице:
какой код надо выполнить,
когда выполнить,
с каким периодом выполнять,
каким способом назначать время следующего запуска агента (периодический или непериодический агент).
Обычно, когда пользователь зашел на страничку сайта, ядро Битрикса смотрит, есть ли агенты, время которых наступило и выполняет их.
Важно. В начале хита еще не объявлена переменная $USER. Её в агентах использовать нельзя.
Можно в агенте создать объект $USER, что-то с ним сделать и уничтожить.
Реальное время запуска агента обычно чуть-чуть позже, чем время, на которое назначен агент. Момент запуска — это когда кто-то зашел на страницу сайта.
Настройки -> Настройки продукта -> Агенты:
Агенты, прежде всего, бывают повторяющиеся или неповторяющиеся. Это зависит от программиста, который написал код агента.
Если функция агента возвращает вызов себя, то агент повторяется.
Если функция агента ничего не возвращает, то агент будет удален из таблицы и больше не запустится. Агент не повторяется.
Программист может сделать агента, который повторится бесконечное число раз. Или только 2-3 раза в зависимости от условий. В списке агентов это увидеть нельзя. Только смотреть в код.
Пример функций агентов повторяющихся бесконечное число раз:
// пример функций агентов
function TestAgentPeriod()
{
AddMessage2Log( "Периодический BX_CRONTAB:".BX_CRONTAB." BX_CRONTAB_SUPPORT:".BX_CRONTAB_SUPPORT );
return "TestAgentPeriod();";
}
function TestAgentNotPeriod()
{
AddMessage2Log( "Непериодический BX_CRONTAB:".BX_CRONTAB." BX_CRONTAB_SUPPORT:".BX_CRONTAB_SUPPORT );
return "TestAgentNotPeriod();";
}
Вычисление следующего времени запуска.
Для повторяющихся агентов есть смыл говорить об интервале запуска и способе вычисления времени следующего запуска.
В данном примере интервал агентов 15 секунд. Один агент периодический, а другой непериодический.
Назначенное время следующего запуска периодического агента вычисляется так:
Старое назначенное время агента + интервал.
Этот способ позволяет запустить агент точное число раз. Например, раз в день запускается агент очистки старых почтовых событий или агент с ежедневным отчетом о посещаемости сайта.
Назначенное время следующего запуска непериодического агента вычисляется так:
Время завершения последнего запуска агента (выполнение return агента) + интервал
Абсолютное большинство агентов непериодические.
Например, агент пересчета рейтингов запускается раз в час. Но если за сутки не было ни одного посетителя, то логичнее выполнить агент один раз и сдвинуть назначенное время следующего запуска на час вперед после запуска. В случае периодического агента, этот код выполнился бы 24 раза за все сутки.
Агенты могут запускаться не только на хитах пользователя, но и на кроне. Но, как это правильно настроить, — тема отдельной большой статьи.
Доброго времени суток! На форуме поднимался как-то уже вопрос о том, как, подтягивая компоненты битрикса по аяксу вытягивать также и скритп, который подключается к компоненту и файл стилей компонента. Тогда решения данного вопроса нормально не было найдено.
И вот теперь есть решение: Более подробно изучил работу с BX.ajax
Сильно расписывать нет времени, посему, сразу готовые наработки.
Итак, есть какой-то компонент. У данного компонента есть файл result_modifier.php
Т.о. в файл /ajax.php размещаем подключение компонента. Указанным запросом получаем данный компонент и помещаем его в контейнер с id="result_container". Все!
В результате файлы script.js и style.css, подключаемые вместе с компонентом, будут также подключаться и при запросе компонента по технологии ajax.
Пример подключения скриптов для ajaxа - хорошая штука. Но столкнулся ещё с проблемой инициализации битриксовых скриптов после ajax-загрузки: в компоненте catalog.section не срабатывают стандартные действия (добавить в корзину, добавить в сравнение). При этом сами скрипты подгрузились.
Мы рассмотрели, какие бывают агенты. Теперь научимся их запускать на кроне. Мы сможем переложить часть задач с пользователей сайта на крон и ускорить время выполнения страниц.
Признаюсь. К этому снаряду я подходил несколько раз. И только с последнего толчка смог осилить этот вес. Сложность в том, что существует большое количество недокументированных констант и опций. Их совместное поведение совершенно не очевидно.
Константы, которые могут влиять на запуск агентов и отправку писем:
BX_CRONTAB
BX_CRONTAB_SUPPORT
NO_AGENT_CHECK
DisableEventsCheck
Опции модуля main, которые влияют на запуск агентов:
agents_use_crontab - по умолчанию не задана
check_agents - по умолчанию не задана
При этом не всё можно прочитать в исходном коде. Файл ядра Битрикса /bitrix/modules/main/include.php обфусцирован.
Нам надо повесить все агенты на крон.
Была подобная статья и учебный курс, но там есть фатальный недостаток: все почтовые события тоже вешаются на крон. Крон работает с минимальной частотой раз в минуту. Получается, что пользователь нажимает «восстановить пароль» и минуту ждет письмо. Еще один недостаток — статья устарела и в ней нет, как настроить резервное копирование по расписанию.
Нам надо, чтобы отправка писем была на хитах, а все агенты и резервное копирование работали на кроне.
Посмотрим, как сейчас обстоят дела в Битриксе:
По умолчанию на кроне вызывается файл /bitrix/modules/main/tools/cron_events.php:
В файле в самом начале стоит define("BX_CRONTAB", true);. Из-за этого в прологе устанавливается другая константа define("BX_CRONTAB_SUPPORT", true);. В результате данный крон-скрипт обрабатывает ТОЛЬКО непериодические агенты.
Исходный код функции обработки агентов.
function CheckAgents()
{
...
//For a while agents will execute only on primary cluster group
if((defined("NO_AGENT_CHECK") && NO_AGENT_CHECK===true) || (defined("BX_CLUSTER_GROUP") && BX_CLUSTER_GROUP !== 1))
return null;
$agents_use_crontab = COption::GetOptionString("main", "agents_use_crontab", "N");
$str_crontab = "";
if($agents_use_crontab=="Y" || (defined("BX_CRONTAB_SUPPORT") && BX_CRONTAB_SUPPORT===true))
{
if(defined("BX_CRONTAB") && BX_CRONTAB===true)
$str_crontab = " AND IS_PERIOD='N' ";
else
$str_crontab = " AND IS_PERIOD='Y' ";
}
...
return CAgent::ExecuteAgents($str_crontab);
}
Настройка агентов на кроне:
Проверьте, чтобы в файле dbconn.php не было установленных констант:
BX_CRONTAB
BX_CRONTAB_SUPPORT
NO_AGENT_CHECK
DisableEventsCheck
Установите опцию, которая запрещает выполнение агента в прологе:
COption::SetOptionString("main", "check_agents", "N");
echo COption::GetOptionString("main", "check_agents", "Y"); // должно вывестись N
Опция, которая влияет на выбор агентов в функции CheckAgents, должна быть не определена или "N".
COption::SetOptionString("main", "agents_use_crontab", "N");
echo COption::GetOptionString("main", "agents_use_crontab", "N"); // должно вывестись N
<?php
$_SERVER["DOCUMENT_ROOT"] = realpath(dirname(__FILE__)."/. ./..");
$DOCUMENT_ROOT = $_SERVER["DOCUMENT_ROOT"];
define("NO_KEEP_STATISTIC", true);
define("NOT_CHECK_PERMISSIONS",true);
define('BX_NO_ACCELERATOR_RESET', true); // чтобы не глючило на VMBitrix 3.1 из-за Zend при отправке бэкапа в облако.
// здесь никакой агент не выполнится. Потому что мы сделали COption::SetOptionString("main", "check_agents", "N");
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
@set_time_limit(0);
@ignore_user_abort(true);
CAgent::CheckAgents(); // а вот тут все агенты выполнятся. И периодические, и непериодические
CEvent::CheckEvents(); // почтовые события мы оставили выполняться на хитах. Но и тут они могут выполняться. Почему нет?
define("BX_CRONTAB", true);
// модуль email-маркетинг
if(CModule::IncludeModule('sender'))
{
\Bitrix\Sender\MailingManager::checkPeriod(false);
\Bitrix\Sender\MailingManager::checkSend();
}
// а еще есть файлик резервного копирования, который запустится, когда его время придет.
require($_SERVER['DOCUMENT_ROOT']."/bitrix/modules/main/tools/backup.php");
?>
Пропишите правило в крон, например * * * * * /usr/bin/php -f /home/bitrix/www/bitrix/php_interface/cron_events.php
Результат
Теперь должно работать. Все агенты периодические и непериодические запускаются на cron. Все почтовые события отправляются на хитах пользователей сразу. Если к отправке письма привязана отправка SMS, то SMS тоже отправится сразу и не будет ждать крона.
Недостатки
Решение вполне рабочее, но есть проблемы:
1. Свой файл /bitrix/php_interface/cron_events.php, как и в старой статье, не будет обновляться.
Битрикс уже добавлял в крон резервное копирование по расписанию. Если они еще что-то добавят, то у вас не появится новый функционал.
2. В Виртуальной машине Битрикса уже настроен крон для файла /bitrix/modules/main/tools/cron_events.php. Вам придется настроить крон на свой файл /bitrix/php_interface/cron_events.php
Решение
Мы написали свой модуль «Агенты на кроне», который очень прост, удобен и лишен этих недостатков.
terseto, установите модуль на тестовый сайт https://labs.1c-bitrix.ru/ а потом скопируйте /bitrix/modules/askaron.agents к себе. Модуль бесплатный. DisableEventsCheck не трогайте, она отключает отправку писем.
Потом установите define("BX_CRONTAB_SUPPORT", true); в dbconn.php
Битрикс рекомендует для ускорения работы сайта переносить выполнение агентов с хитов пользователей на крон.
Агенты — это служебные задачи, которые запускаются в определенное время. Например, пересчет рейтинга пользователей сайта запускается раз в час.
Агенты запускаются, когда какой-нибудь пользователь заходит на сайт. Если при посещении страницы вдруг запустился пересчет рейтингов, то страница может дольше открываться.
Разумно запускать выполнение агентов с помощью служебной программы cron, а не на хитах пользователей.
В Битриксе нет понятного инструмента для переноса агентов на крон.
Есть несколько советов и моя статья, как создать отдельный файл, как настроить крон и установить несколько непонятных констант.
Такие решения рабочие, но требуют настройки, изучения, и свой отдельный крон-файл не будет обновляться.
Мы используем стандартный файл Битрикса /bitrix/modules/main/tools/cron_events.php. Крон уже настроен в Виртуальной машине Битрикса для этого файла, и делать ничего не надо.
На других хостингах вам придется настроить правило, например: * * * * * /usr/bin/php -f /home/bitrix/www/bitrix/modules/main/tools/cron_events.php
Об этом написано в подсказке на странице настроек:
С модулем «Агенты на кроне» будут все возможности, которые появятся в Битриксе при будущих обновлениях.
Мы очень старались сделать модуль простым и понятным. Поэтому он немножко платный. Срок демо-периода 30 дней. Демо-версия полностью функциональная.
Модуль бесплатный.
UPD 25.11.2014 Частые вопросы:
— Нужно ли прописывать константу BX_CRONTAB_SUPPORT в dbconn.php?
— Нет, необязательно. С нашим модулем агенты не зависят от константы BX_CRONTAB_SUPPORT.
Но от этой константы в Битриксе зависит отправка почты.
Если вы напишите define("BX_CRONTAB_SUPPORT", true) ; в dbconn.php, то почтовые события будут срабатывать на кроне раз в минуту.
Если уберете константу, то почта будет отправляться без задержки на хитах пользователей.
— Нужно ли прописывать константу BX_CRONTAB в dbconn.php?
— Нет, ни в коем случае, забудьте про неё. Константа BX_CRONTAB уже прописана в служебном файле, который вызывается кроном. В dbconn.php для всех страниц её включать нельзя.
Дмитрий, важнейшее преимущество модуля, кроме простоты настроек в том, что вместе с агентами на крон не переносятся почтовые сообщения. Очень бесит, когда письма о заказе приходится ждать минуту.
Модуль не будет трогать вашу почту. С модулем вы сами решаете переносить почту на агенты или нет с помощью константы BX_CRONTAB_SUPPORT
Зайцев Артемий, я только за упрощение, просто в данном случае просто не понятно что именно упрощается. Наскоком на одном из проектов я установил модуль, но возникла проблема с пингами в задачах (наверное вы в курсе, пишут об этом в отзывах) и получается прежде чем упрощать все равно приходится разбираться в том какие действия выполняет модуль, и что упрощается). Иными словами - чтобы это упрощение вкусить - нужно понять что мне нужно делать и что не нужно.
Пока что правильно я вас понял - суть упрощения в том что "не нужно настраивать в ядре Б24 опции связанные с запуском агентов - их делает сам модуль", но при этом крон настраивать нужно?
Т.е конкретно из стандартного мануала вычеркиваем пункты
Дмитрий, что касается неправильной работы каких-то отдельных агентов - надо обращаться в разработчику агентов, то есть к Битриксу, если это модуль задач. Битрикс обычно просит удалить наш модуль и настроить стандартным способом. Регламент технической поддержки не позволяет, что-либо проверять, если есть сторонние модули.
Задача: С генерировать символьные коды для разделов или элементов инфоблока - если они не заданы [spoiler] Используя скрипт предложенный Николаем Ефремовым делаем так:
1/ открываем командную строку PHP - Рабочий стол - Настройки - Инструменты - Командная PHP-строка [/bitrix/admin/php_command_line.php] Скопировать в область кода следующий скрипт
2/ Определяемся с инфоблоком - ниже в скрипте в параметр $arParams['IBLOCK_ID'] нужно записать его ID
3/ Решаем, нужно ли нам генерировать совсем уникальные коды. Можно вначале пройтись и создать не повторяющиеся, а для повторяющихся добавить в конце ID. За это отвечает параметр $arParams['IS_ADD_RAND'] - {true|false}
4/ Указываем шаг выборки - параметр $arParams['LIST_CNT'] - большим не стоит делать, максимум 100 элементов за раз
5/ Настраиваем параметры транслита. За это отвечает массив $arTransParams
6/ Указываем для чего будем проводить генерацию - для разделов или для элементов - параметр $arParams['TYPE_WORK'] - возможные значения - {section | element}
7/ Жмем кнопку выполнить - прогнать скрипт нужное количество раз
Допустим, таблица сделок, или лидов, или любой другой список, основанный на гридах (в CRM таких данных чуть менее, чем полностью). И допустим, что эта таблица должна выглядеть так, как установил админ, или другой супер-юзер. Решение под катом. [spoiler] Когда я столкнулся с такой задачей, я полез прежде всего в ядро, что советую делать всегда. Полез в main.interface.grid, и узнал, откуда она берет все настройки списка:
GRID_ID постоянен (для конкретного списка), первое и так константа, осталось как-то заменить этот метод на свой. Но сначала посмотрим внутренности этого метода.
Там я увидел кеш:
Что это значит? А то, что мы можем переопределить его до вызова грида, тем самым указав любые данные, какие только захотим. Этим методом я кстати когда-то пользовался для добавления отсутствующих товаров в корзину.
Проверим - как хранится self::$cache. Нам свезло! Это protected.
То есть, достаточно из дочернего класса переопределить эту переменную. Что мы и делаем, быстренько накидывая такой метод в дочернем классе:
class CUserOptionsOver extends CUserOptions {
public static function SetBaseUserCache($user_id, $base_user_id, $category, $name, $default_value = false) {
if ($base_user_id == $user_id) {
return;
}
if (!isset(parent::$cache[$user_id])) {
parent::$cache[$user_id] = array();
}
if (!isset(parent::$cache[$user_id][$category])) {
parent::$cache[$user_id][$category] = array();
}
parent::$cache[$user_id][$category][$name] = parent::GetOption($category, $name, $default_value, $base_user_id);
}
}
Суть кода проста - перетираем текущий кеш-массив пользователя на массив супер-юзера (естественно только для конкретной категории и имени переменной).
Теперь нам надо понять - какие значения у $category и $name. Если отмотаете в начало поста, то узнаете, что $cateogory это константа main.interface.grid, а $name это некий $arParams["GRID_ID"], который ставится извне. В моем случае внешний компонент, подключающий грид, это список сделок, поэтому я полез туда (в crm.deal.list).
Второй переменной идет ID пользователя, с которого надо взять все настройки.
Смотрим результат под любым пользователем - видим, что и колонки изначально стоят нужные, и изменить их порядок или добавить новые - невозможно. Что и требовалось сделать.
Резюмирую! Если вы хотите заморозить грид, порядок действий:
1. Создаете класс с методом выше. Менять его даже и не требуется, если только не захотите более удобно оформить порядок переменных. 2. Узнаете GRID_ID. 3. Вызываете метод перед вызовом непосредственно грида. Это может быть на самой странице компонента в публичной части (хотя в случае КП я бы не стал доверять даже публичке, она может меняться с обновлениями). Поэтому, лучше вызывать его в каком-то обработчике - например, OnBeforeProlog. 4. PS: По идее неким похожим способом можно легко и просто заморозить списки и формы в админке, но мне пока этого не требовалось.
Я не зря все подробно расписал - как шел, как искал. Чтобы обратить внимание новичков - что решения прежде всего стоит искать в самих интерфейсах и пользовательских инструментах. А если этого нет - сразу лезть в код. Какого-то промежуточного звена в нашем деле нет.
Дрёмин Станислав написал: В result_modifier брал настройки супер-юзера через CUserOptions::GetOption и записывал их через CUserOptions::SetOption для конкретного юзера.
Вот тут небольшой минус - перетираются собственные настройки пользователя. В случае, например, модуля из Маркета это делать нельзя - модуль удалили > настройки должны остаться.
Дрёмин Станислав, так прост вытащи через GetOption массив, потом через array_merge() добавь то что нужно и запиши, тогда не слетит ничего. А если ты просто передаешь массив с параметрами то он естественно затрет уже установленные пользователем параметры
require_once ($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/classes/general/csv_data.php";);
$csvFile = new CCSVData('R', true);
$csvFile->LoadFile($_FILES['csv']['tmp_name']);
$csvFile->SetDelimiter(',');
while ($arRes = $csvFile->Fetch()) {
ec($arRes);
}
Собственно: - подключаем файл класса работы с CSV - создаем объект класса, указываем, что будет использоваться разделитель (R, есть еще фикс.поля F), и первая строка содержит заголовки (true); можно не указывать эти параметры и задать отдельными методами
- загружаем файл - ставим делиметер, где допустимые параметры: \t (табуляция), запятая, пробел, точка с запятой. - бежим как при обычной выборке из базы (напомню, Fetch возвращает НЕ обработанные данные, а GetNext безопасные).
Эту фичу наверное нужно использовать для того что бы избежать всяческих проблем с кодировкой и прочими настройками которые Битрикс учитывает. Антон там в строке подключения библиортеки лишнее
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».