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 безопасные).
Semenov Roman, да никто же не спорит Тут вопрос скорее не "почему не использовали именно эту фичу", а "зачем понадобилось писать прослойку, да еще и не очень удобную"
Эту фичу наверное нужно использовать для того что бы избежать всяческих проблем с кодировкой и прочими настройками которые Битрикс учитывает. Антон там в строке подключения библиортеки лишнее
Битрикс рекомендует для ускорения работы сайта переносить выполнение агентов с хитов пользователей на крон.
Агенты — это служебные задачи, которые запускаются в определенное время. Например, пересчет рейтинга пользователей сайта запускается раз в час.
Агенты запускаются, когда какой-нибудь пользователь заходит на сайт. Если при посещении страницы вдруг запустился пересчет рейтингов, то страница может дольше открываться.
Разумно запускать выполнение агентов с помощью служебной программы 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 для всех страниц её включать нельзя.
В одном из моих личных проектов потребовалось сделать приложение 2 типа для bitrix24 и работать с его API. Я человек ленивый, поэтому решил написать «простенькую» обёртку поверх REST- вызовов.
// инициализируем бибилиотеку для работы с B24
$obB24App = new \Bitrix24\Bitrix24();
$obB24App->setApplicationScope($arParams['B24_APPLICATION_SCOPE']);
$obB24App->setApplicationId($arParams['B24_APPLICATION_ID']);
$obB24App->setApplicationSecret($arParams['B24_APPLICATION_SECRET']);
// выставляем настройки, зависящие от пользователя
$obB24App->setDomain($arParams['DOMAIN']);
$obB24App->setMemberId($arParams['MEMBER_ID']);
$obB24App->setAccessToken($arParams['AUTH_ID']);
$obB24App->setRefreshToken($arParams['REFRESH_ID']);
// получили информацию по текущему пользователю из Bitrix24
$obB24User = new \Bitrix24\User\User($obB24App);
$arCurrentB24User = $obB24User->current();
Пример получения списка задач
/**
* объект для работы с задачами
**/
$obTasks = new \Bitrix24\Task\TaskItems($obB24App);
/**
* список задач из B24
* @var $arB24Tasks array */
$arB24Tasks = $obTasks->getList(
array("ID" => 'desc'),
array('RESPONSIBLE_ID' => $arUser['B24_USER_ID']),
array('ID','TITLE','CREATED_DATE','DEADLINE','STATUS','REAL_STATUS','STATUS_CHANGED_DATE','GROUP_ID','CHANGED_DATE'),
null);
Я её периодически обновляю, но уже сейчас она вполне пригодна для работы. Критика и пулл-реквесты приветствуются.
Булгаков Никита
Проблема в том, что битрикс сменил UI авторизации и моя библиотека перестала работать. До момента, пока не переписал её под новый UI... У Вас если происходят ошибки - смотрите адрес скрипта где эта ошибка произошла и задавайте вопрос в ISSUES на гитхабе разработчику библиотекы
Хочу кратко описать как работать с XML в Битриксе правильно. Ибо не так давно (ну, для меня было неожиданностью по крайней мере) API для оного обновилось, и если раньше работали в лоб с массивом из XML, то сейчас для этого есть удобные инструменты.
if ($node = $xml->SelectNodes('/videos/video/pics')) {
print_r($node->children());
}
Где каждый такой чилдрен будет объектом CDataXMLNode.
Этого вполе достаточно для работы. Но более подробно изучить класс вы сможете по пути из п.1.
Дополнение:
1. Если формат XML с двоеточиями (неймспейсы которые, хз как правильно его называть):
<media:title></media:title>
то перед парсингом, надо сделать следующее:
$xml->delete_ns=false;
Спасибо за совет техподдержке.
2. Можно использовать не LoadString, а Load, которой передать абсолютный путь до файла. Метод хорош тем, что автоматически вычленяет кодировку из XML-файла (encoding) и конвертит файл в кодировку сайта. Есть минус - если кодировки в файле не найдется, будет считать, что файл находится в windows-1251 кодировке.
Пришлось подробно изучить вопрос откуда в Битриксе «неожиданно» возникают глобальные переменные. В некоторых случаях между $CODE и $_REQUEST["CODE"] нет разницы.
Странно? Почему $CODE содержит значение? Первая мысль: «настройка register_globals включена». Но на виртуальной машине и на хостинге она выключена. Тем более известно, что эта опция потенциально опасна при неправильном использовании и даже удалена в версии php 5.4.0.
После длительного исследования была найдена функция, которая вызывается при подключении заголовка /bitrix/header.php:
На странице /index.php любая используемая переменная будет глобальной. $GLOBALS или global писать не надо.
Внутри функций своё изолированное пространство имен, и к глобальной переменной можно обращаться через массив $GLOBALS или ключевое слово global.
<?// index.php
// Пример 1. Установка глобальной переменной до функции
function ShowGlobalValue()
{
echo $GLOBALS["value"];
}
$value = 1;
ShowGlobalValue(); // покажет 1
?>
<?// index.php
// Пример 2. Установка глобальной переменной внутри функции
function SetGlobalValue()
{
$GLOBALS["value"] = "1";
}
SetGlobalValue();
echo $value; // покажет 1
?>
Фрагмент функции FormDecode() делает из переменной $_GET["CODE"] глобальную переменную $CODE. Поэтому /index.php?CODE=Artemy всегда создает переменную $CODE=Artemy:
foreach($_GET as $key => $val)
if(!isset($superglobals[$key]))
$GLOBALS[$key] = $val;
Аналогично из $_SERVER["DOCUMENT_ROOT"] получается глобальная переменная $DOCUMENT_ROOT.
Выводы:
Несмотря на то, что сейчас везде PHP 5.3 и PHP 5.4, в Битриксе эмулируется register_globals=on. Это означает, что переменные перед использованием на странице надо объявлять. Иначе они могут быть неожиданно получены из URL.
Компонент вызывается функцией $APPLICATION->IncludeComponent(), значит в нем пространство имен изолировано.
Включаемый файл вызывается функцией $APPLICATION->IncludeFile(). В нем тоже пространство имен изолировано.
Настоятельно не рекомендуется писать код на странице. Пишите код внутри компонентов, или во включаемых файлах, или в функциях.
На странице можно писать короче $CODE вместо $_REQUEST["CODE"]. Но лучше $_REQUEST["CODE"], потому что такой код при копировании в другое место не вызовет странных ошибок.
Спасибо за уточнение. В bitrix:catalog и не должно работать из-за особенности компонента. Если вы используете комплексный компонент, то фильтр нужно задавать внутри шаблона компонента bitrix:catalog, после вызова компонента catalog.smart.filter, но перед 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
Решение
Мы написали свой модуль «Агенты на кроне», который очень прост, удобен и лишен этих недостатков.
Именно так, а периодические на хитах. Но он утверждает, что все агенты, а не только непериодические. Это-то и вызвало вопрос.
Значит всё ещё актуальна необходимость установки вашего модуля или ручного изменения параметров check_agents / agents_use_crontab и добавления своего крон-скрипта?
В той статье, кстати, крон-скрипт обновили в марте этого года. Не подскажете, какой из скриптов оптимальнее использовать: из той статьи или из вашей?
Столкнулся с довольно странным поведением (сначала думал) продукта, убил прилично времени. Так что, поделюсь этими граблями. Грабли относятся к БД с транзакциями (INNODB в MySQL, в частности).
Суть - пытаемся записать в Журнал сообщение при добавлении поста в форум. В данном виде все отлично работает. Но стоит нам откомментировать две нижние строчки, как ничего не добавляется - автоинкремент таблицы Журнала увеличивается, но лог не пишется. Это сейчас на простейшем обработчике 2 + 2 связываются легко, но стоило времени дойти до этого
В чем магия? Дело в том, что добавление постов в форум (а может и в блоги) окружено такой конструкцией в компонентах:
StartTransaction
AddMessage()
Commit OR RollBack
Для непосвященных, основная фишка транзаций - все-все что мы делаем после StartTransaction, упадет в базу только после Commit. Если же делается RollBack, то ничего не добавится. Вообще ничего.
И вот в эти грабли я и попал - в AddMessage генерировалась ошибка, а далее (в компоненте) делался RollBack. Соответственно, запись не ложилась в таблицу.
А можно ли закрывать транзакцию, если ее не открывать? У тебя получается $GLOBALS['DB']->RollBack(); дважды. Один ты закрыл, a другой, наверняка, еще где-то.
Артемий, все можно, только будет ли толк )) тоже самое можно сказать человеку закрыть два раза дверь не открывая, он команду получит, но ничего делать не будет, т.к. дверь уже закрыта =)
Большое спасибо, Антон, за пример! Как правильно заметил Андрей, в документации не указана переменная $arTemplateParameters - кучу времени убил, чтобы разобраться, почему дополнительные параметры не подтягиваются. Битриксу как всегда двойка в этой области.
Долганин Антон написал: под рукой. Вот требуется вам сохранять элемент со свойством, передавая просто название элемента списка, и не париться о том, есть ли такой вариант, или надо добавить н
Да это старо как битрикс! А вот как сделать если ты хочешь добавить в шаблон bitrix:catalog кроме стандартного набора еще один компонент и при этом использовать настройки комплексного компонента ($component), но не просто вынести эти настройки во вкладку "Дополнительно", а создать свою вкладку, по аналогии с существующими (настройки ТОПа или "С этим товаром покупают")??? Вот это как реализовать? Как добавить свою группу в параметрах шаблона?
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».
Антон там в строке подключения библиортеки лишнее