Итак после первых плагинов для ВордПресс и джумла пришла пора сделать что-то похожее в Битрикс.
Наш путь познания разных движков для сайтов проходит под идеей принести один конкретный новый функционал, а именно принятие оплаты по покупателя при самовывозе, то есть это либо наличными либо по банковской карте в момент, когда клиент приходит к вам в офис.
И вот так получилось, что свежие мозги прошлись по ВордПрессу, Джумла и теперь взялись за Битрикс.
Сразу хочу сказать, что привыкнуть можно к любой CMS, все дело в обстоятельствах и наличии времени и желания.
Главное отличие отечественной CMS - оплата вперед
Итак не нужные проблемы у Битрикс начинаются уже на этапе установки, разработчики как бы говорят вам - нафига ты сюда лезешь (это наша корова и мы сами доить ее будем).
Проблемы с установкой
Имеется ввиду, что так называемая демо версия (на месяц) виснет при установке и до конца ну никак не доходит.
Мы сначала подумали, что это потому, что мы устанавливаем на локалхост или потому, что это демо версия, но оказалось в последствие, что так и должно быть. То есть и при установке демо или при установке нового сайта в рабочем варианте Битрикс - установка зависала на разных этапах по непонятным причинам.
С установкой демо версии на локалхост мы через некоторое время все-таки разобрались. Оказалось,что лучше не читать инструкции и мануалы, а сразу лезь в логи ошибок апаче, ибо ошибки от битрикс там естественно были.
В нашем случае установка падала в файле random.php в функции getStringByCharsets:
Скрытый текст
public static function getStringByCharsets($length, $charsetList)
{
$charsetVariants = strlen($charsetList);
/*$randomSequence = static::getBytes($length); // 117 строчка$result = '';
for ($i = 0; $i < $length; $i++)
{
$randomNumber = ord($randomSequence[$i]);
$result .= $charsetList[$randomNumber % $charsetVariants];
}*/
return "sdfdsfsdfdsfd";//$result;
}
Как видно выше мы тупо закомментировали почти весь код и просто возвращаем теперь не рандомную какую-то последовательность символов, а просто от балды константу "sdfdsfsdfdsfd".
И это сработало установка прошла далее гладко. О чем это говорит? Тестирование своих продуктов в битрикс "оставляем желать лучшего".
Но как мы знаем любая CMS это просто набор файлов php и некоторых других типов файлов, расписанных по разным каталогам по задуманной разработчиками какой-то их субъективной логике.
Таким образом мы копируем один рабочий сайт на Битриксе к себе на локалхост. Он заводится в целом без проблем, мы его обновляем из админки, все пока хорошо.
Огромное количество файлов
Но вот, что бросается в глаза, в чем отличие Битрикс, это огромное количество файлов и каталогов, у нас при скачке получилось около 230 тысяч. Соответственно это заняло не просто большое количество времени, а огромное. Пришло дома , где интернет 100МБс, скачать на диск и уже на работе с диска устанавливать. Это я к тому, что с джумлой и вордпресс у вас таких проблем не возникает.
Огромное количество таблиц в базе данных
Но без базы данных ничего не работает (как мы знаем) и это отдельная проблема, так как в Битрикс и количество таблиц в базе данных очень много, больше 200. И нам пришлось скачивать базу частями по несколько таблиц, так как phpmyadmin например не мог загрузить сразу всю базу целиком из файла sql. По другому мы не знали как, но это возможно от не знания, как можно.
Все это опять к вопросу, что в этом не было бы необходимости, если бы установка работала нормально.
Переходим к изучению как устроен битрикс
Сразу выясняем, что есть новое ядро D7 и есть старое и вроде как живут они вместе.
Есть каталог bitrix где все, что относится к ядру Битрикс и там лучше не располагать свои самопальные компоненты и модули ибо они затрутся при обновлении Битрикс. А где располагать тогда? Лучше во вновь придуманном каталоге local. Так мы и сделаем.
Много сайтов - один движок, одна база данных
У Битрикс есть своя особенность. Битрикс взял за идею предоставлять разработчику создавать неограниченное количество сайтов на одном движке Битрикс и в одной базе данных, то есть в одной админке. Хорошо это или плохо?... Платишь ты за движок один раз, а пользуешься движком во всех сайтах, вроде как не так обидно.
Но вот надо тебе перенести один сайт на другой движок и как-то надо отделить данные других сайтов, а база одна, таблицы общие и вроде как сразу проблема.
Нюансы установки и удаления модулей в битрикс
Итак, в битрикс надо писать инсталлятор модуля самому (в отличии от вордпресс и джумла например). А именно для этого создается каталог install (как часть состава вашего модуля), где вы и управляете логикой установки и удаления модуля, сами пишете какие файлы в какие папки копировать. То есть вы можете скопировать куда и что угодно и это как-то не есть правильно (бесконтрольно).
События
Тут как и во всех движках можно подписаться на события, которые испускают нужные нам компоненты или модули. Нас например заинтересовал OnAdminSaleOrderViewDraggable. Нам это надо, чтобы получить содержание открываемого заказа и сохранить данные заказа в своем модуле.
init.php
Отличие Битрикс от ВордПресса и джумлы ещё в том, что часть своего кода приходится писать в общих разделяемых файлах, а именно у нас конкретно в local\php_interface\init.php. Как я понял init.php предназначен для подключения своих модулей и компонент.
Таким образом нет полной изоляции от действий других разработчиков, то есть другой разработчик также открывает init.php, добавляет свой код, видит ещё наш код, думает: не из-за него ли глючит его сайт и конечно же удаляет наш код или временно отключает...
Надо учитывать, что если вы создадите init.php каталоге local/php-interface, то в bitrix/php_interface он вызываться уже не будет.
В init.php нам пришлось добавить строчку кода:
$request = \Bitrix\Main\Context::getCurrent()->getRequest();
if( $request->isAdminSection())
{
if( $request->getRequestedPage() == '/bitrix/admin/sale_order_view.php' )
require_once( $_SERVER['DOCUMENT_ROOT'] . '/local/modules/paymentacceptance/autoload.php');
}
Заказ а админке
Вот тут надо сказать, что в битрикс как и в ВордПресс и как в джумле для админки заказа есть обратная связь, то есть можно подписаться на событие при открытии заказа, получить состав заказа и добавить на форму свой визуальный блок:
Скрытый текст
<?php
use Bitrix\Main\Loader;
use Bitrix\Main;
use Bitrix\Main\ModuleManager;
use Bitrix\Main\Localization\Loc;
Loc::loadMessages(__FILE__);
$ff = CJSCore::Init(array("jquery"));
$loaded = Bitrix\Main\Page\Asset::getInstance()->addJs('/local/modules/paymentacceptance/js/jquery-ui.js');
$loaded = Bitrix\Main\Page\Asset::getInstance()->addJs('/local/modules/paymentacceptance/js/bit_drv_kkt.js');
$APPLICATION->SetAdditionalCSS("/local/modules/paymentacceptance/css/bit_drv_kkt.css");
\Bitrix\Main\EventManager::getInstance()->addEventHandler("main", "OnAdminSaleOrderViewDraggable", array("PaymentAcceptance123", "onInit"));
class PaymentAcceptance123
{
public static function onInit()
{
return array("BLOCKSET" => "PaymentAcceptance123",
"getScripts" => array("PaymentAcceptance123", "mygetScripts"),
"getBlocksBrief" => array("PaymentAcceptance123", "mygetBlocksBrief"),
"getBlockContent" => array("PaymentAcceptance123", "mygetBlockContent"),
);
}
public static function mygetBlocksBrief($args)
{
$id = !empty($args['ORDER']) ? $args['ORDER']->getId() : 0;
return array(
'payments_pickup' => array("TITLE" => "Оплата заказа при самовывозе")
);
}
public static function mygetScripts($args)
{
$BIT_KKT_TOKEN = COption::GetOptionString('paymentacceptance', 'BIT_KKT_TOKEN');
if( $BIT_KKT_TOKEN != "")
$BIT_KKT_TOKEN = "\nvar BIT_KKT_TOKEN='$BIT_KKT_TOKEN';";
$BIT_BNK_TRM_TOKEN = COption::GetOptionString('paymentacceptance', 'BIT_BNK_TRM_TOKEN');
if( $BIT_BNK_TRM_TOKEN != "")
$BIT_BNK_TRM_TOKEN = "\nvar BIT_BNK_TRM_TOKEN='$BIT_BNK_TRM_TOKEN';";
$BIT_PROG_URL = COption::GetOptionString('paymentacceptance', 'BIT_PROG_URL');
if( $BIT_PROG_URL != "")
$BIT_PROG_URL = "\nvar BIT_PROG_URL='$BIT_PROG_URL';";
$ORDER = $args["ORDER"];
$orderID = $ORDER->getId();
if($orderID>0)
$orderID = "\nvar orderID=$orderID;";
return '<script type="text/javascript">'.$BIT_KKT_TOKEN.$BIT_BNK_TRM_TOKEN.$BIT_PROG_URL.$orderID.'</script>';
}
public static function mygetBlockContent($blockCode, $selectedTab, $args)
{
$result = '';
$id = !empty($args['ORDER']) ? $args['ORDER']->getId() : 0;
if ($selectedTab == 'tab_order')
{
$mdl = Loader::includeModule('paymentacceptance');
if ( ! $mdl )
{
}
if ($blockCode == 'payments_pickup')
{
$jsn = [];
$ORDER=$args['ORDER'];
$sum= $ORDER->getPrice();
$isPaid = $ORDER->isPaid();
$basket = $ORDER->getBasket();
//$basket = $ORDER->getBasketItems();
$id = \Bitrix\Main\Engine\CurrentUser::get()->getId();
$bb = \Bitrix\Main\Engine\CurrentUser::get()->isAdmin();
$login = \Bitrix\Main\Engine\CurrentUser::get()->getLogin();
$fio = \Bitrix\Main\Engine\CurrentUser::get()->getFullName();
$purchases=[];
foreach( $basket as $kk => $itm)
{
$item=[];
$item["productName_1030"]= $itm->getField('NAME');
$item["price_1079"]= $itm->getPrice();
$item["qty_1023"]= $itm->getQuantity();
//$item["getWeight"]= $itm->getWeight();
$item["getVatRate"] = $itm->getVatRate();
$item["unit_2108"]=0;
$item["paymentFormCode_1214"]=2;
$item["productTypeCode_1212"]=3;
$item["tax_1199"]= 6;
//$item["additionalAttribut_1191"] = "что-то дополнительное";
$purchases[] = $item;
}
$jsn ["purchases"] = $purchases;
$jsn ["cashierInn_1203"] = $fio;
$jsn ["taxationType_1055"] = 5;
$jsn ["receiptType_1054"] = 1;
//$jsn ["sendToEmail_1008"] = "";
$jsn ["electronically"] = false;
$json_data = json_encode($jsn ,JSON_PRETTY_PRINT| JSON_UNESCAPED_UNICODE);
$result = 'Заказ № '.$id.'<BR>Сумма к оплате: <span id="k_oplate">'.$sum.'</span> <div id="paymentBtns"><button id="btnCash">Наличными</button> <button id="btnECash">Банковской картой</button></div><br><textarea id="json_data" style="width:100%">'.$json_data.'</textarea>';
}
}
$aaaa= 123;
return $result;
}
}
У нас тут реализовано например оплата наличными или по карте при самовывозе.
На гитхабе мы как обычно выложили этот модуль для битрикс, можно скачать, установить и даже пользоваться https://github.com/PavelDorofeev/API-receipt-fiscalization-for-CMS-and-CRM.
Сделали небольшое видео? если кому вдруг стало интересно, так как всегда лучше один раз увидеть, чем 10 раз прочитать. Модуль бесплатный, думаю тут никакой рекламы нет.
Убрал видео, т.к. минусует кто-то, наверное из-за видео, странно и не понятно...
Что осталось из непонятого, можно ли было сделать как-то проще и не городить такой огород....
Вопрос знатокам:
Можно ли не редактировать init.php, а как-то добавить из админки старт своего модуля, чтобы он автоматически загружался?
Немного подумав найден вполне приличный способ не править исходники Битрикс нигде, но это уже в комментариях смотрите.
Комментарии (28)
w0lf
18.09.2024 10:32+1Можно ли не редактировать init.php, а как-то добавить из админки старт своего модуля, чтобы он автоматически загружался?
Конечно можно. Добавьте в корень модуля файл include.php , где пропишите какие классы должны быть загружены автолоадом:
CModule::AddAutoloadClasses('mlwebformsantispam', [ 'Multiline\MlWebFormsAntispam\MlWebFormsASProc' => 'lib/mlwebformsantispamprocessor.php', '\Multiline\MlWebFormsAntispam\MlWebFormsASProc' => 'lib/mlwebformsantispamprocessor.php', ]);
kkmspb Автор
18.09.2024 10:32Добавьте в корень модуля файл include.php
Спасибо за наводку. Но чего-то include.php никем не вызывается (отладчиком смотрю), пойду почитаю немного доки.
из папки local\modules похоже ни один модуль через include.php не аутолодится...
w0lf
18.09.2024 10:32А вообще модуль в Битрикс корректно установлен, в таблице b_modules он есть с датой активации?
kkmspb Автор
18.09.2024 10:32А вообще модуль в Битрикс корректно установлен, в таблице b_modules он есть с датой активации?
Нормально устанавливается и деинсталлируется. В b_module он есть (paymentacceptance 2024-09-18 14:10:23 )
kkmspb Автор
18.09.2024 10:32DoInstall() и DoUnInstall() срабатывают, может туда регистрацию автозагрузки прописать?
kkmspb Автор
18.09.2024 10:32Конечно можно. Добавьте в корень модуля файл include.php , где пропишите какие классы должны быть загружены автолоадом:
Похоже это совсем не то, что я хотел. Получается, что include.php вызывается, когда мы выполняем Loader::includeModule('paymentacceptance'); , то есть мне надо все-равно где-то в коде прописать Loader::includeModule('paymentacceptance'); - правильно?
И чего-то я в базе данных не нашел, где хранятся настройки автозагрузки (модулей, классов и т.д.)
И еще у меня нюанс, что модуль для админки пишу, может это важно...
w0lf
18.09.2024 10:32Мы тоже разрабатываем модули у которых есть часть, работающая в админке Битрикса, ничего дополнительно вручную вызывать не нужно, корректно написанный в соответствие с документацией модуль подключается в админку автоматически. В базе никакие настройки автозагрузки не хранятся, только факт активности модуля.
kkmspb Автор
18.09.2024 10:32Мы тоже разрабатываем модули у которых есть часть, работающая в админке Битрикса, ничего дополнительно вручную вызывать не нужно, корректно написанный в соответствие с документацией модуль подключается в админку автоматически
Я за вас рад конечно, но проблемка для меня не решена. Если бы вы поконкретнее показали кто и когда в коде у вас вызывает include.php было бы очень замечательно. А так у меня есть подозрения, что все равно надо править файл init.php. По интернету помониторил не нашел решения.
kkmspb Автор
18.09.2024 10:32Похоже разобрался как обойтись без правки init.php!
Надо при установке модуля в методе DoInstall() подписаться на событие например OnProlog модуля main.
$eventManager = \Bitrix\Main\EventManager::getInstance(); $bb = $eventManager->registerEventHandler( "main", "OnProlog", $this->MODULE_ID, "paymentacceptance", "onProlog" );
В этом случае система в таблице b_module_to_module зарегистрирует наше событие.
Потом открывая страницу будет испускаться событие OnProlog для нашего модуля paymentacceptance. Но перед этим система попытается загрузить модуль сначала и будет вызван include.php в каталоге нашего модуля. А тут мы уже знаем, что делать.
Главное, что это работает! И не надо править исходники ядра битрикс.
Mausglov
18.09.2024 10:32Потом открывая страницу будет испускаться событие OnProlog для нашего модуля paymentacceptance
Нет, неверно. Будет срабатывать событие OnProlog для модуля main. А поскольку Вы зарегистрировали обработчик для этого события, и при регистрации указали на свой модуль, то Ваш модуль будет подключен перед вызовом обработчика.
Вам никто не мешает для своего модуля сделать событие OnProlog - соответственно, обработчик на него можно будет зарегистрировать как:$eventManager->registerEventHandler( "yourmodule", "OnProlog", ... );
События описаны в этой части курса. Ссылки в конце тоже полезны ( в чём-то даже полезнее самой главы)
kkmspb Автор
18.09.2024 10:32Нет, неверно. Будет срабатывать событие OnProlog для модуля main. А поскольку Вы зарегистрировали обработчик для этого события, и при регистрации указали на свой модуль, то Ваш модуль будет подключен перед вызовом обработчика.
Я с вами не согласен. Событие OnProlog для модуля main не существует.
Просто всегда стандартно при загрузки выполняется код, который читает записи в базе данных (в таблице b_module_to_module ). Находит как в коде ниже обработчики (связи с другими модулями) для "main" и "OnProlog" и вызывает их связанные методы через ExecuteModuleEventEx. Просто событиями обычно принято называть что-то, что генерирует ОС, а тут просто зачем-то решили событиями обозвать (не суть).
bitrix\modules\main\include\prolog_before.php
bitrix\modules\main\include.php
CMain::PrologActions(); - это не событие, а просто вызов статического метода класса.
Далее:
foreach (GetModuleEvents("main", "OnProlog", true) as $arEvent) { ExecuteModuleEventEx($arEvent); }
то Ваш модуль будет подключен перед вызовом обработчика
Тут не спорю, в этом и есть весь смысл, т.к. далее и будет вызван include.php в каталоге вашего модуля. Но сам по себе include.php он никак не вызовется.
Вам никто не мешает для своего модуля сделать событие OnProlog - соответственно, обработчик на него можно будет зарегистрировать как:
$eventManager->registerEventHandler( "yourmodule", "OnProlog", ... );
Вот где как ни в в DoInstall() установщика модуля это сделать? И только не yourmodule, а так:
$eventManager->registerEventHandler( "main", "OnProlog", $this->MODULE_ID, "paymentacceptance", "onProlog");
Кстати и в документации так и сказано:
registerEventHandler - функция для регистрации обработчиков, расположенных в модулях и использующихся для взаимодействия между модулями системы. Эту функцию необходимо вызвать один раз при инсталляции модуля, после этого функция-обработчик события будет автоматически вызываться в определённый момент, предварительно подключив сам модуль.Но честно говоря документация битрикс мне не заходит, как-то много красивых слов, когда все просто на самом деле.
w0lf
18.09.2024 10:32Для интереса посмотрел код коммерческих модулей из Marketplace Bitrix - в основном используют такой же подход, вешают на OnBeforeProlog модуля main. Многие даже в "старом" стиле через RegisterModuleDependences а не registerEventHandler.
Mausglov
18.09.2024 10:32И чего-то я в базе данных не нашел, где хранятся настройки автозагрузки (модулей, классов и т.д.)
В файле include.php модуля Вы и описываете всё, что относится к загрузке модуля - регистрация классов в автозагрузку, подключение модулей, от которых зависит Ваш модуль, языковые фразы.
voidstrx
18.09.2024 10:32У меня тоже висла установка Битрикс, пока не исправил конфиги mysql. Устанавливал на wsl debian.
kkmspb Автор
18.09.2024 10:32пока не исправил конфиги mysql.
Да mysql.ini я тоже правил, увеличивал таймауты и лимиты памяти, но мне не помогло.
voidstrx
18.09.2024 10:32transaction-isolation = READ-COMMITTED
innodb_flush_log_at_trx_commit = 2 //без этой строчки всё висло
innodb_flush_method = O_DIRECT
thread_cache_size = 4
innodb_strict_mode=OFFkkmspb Автор
18.09.2024 10:32innodb_flush_log_at_trx_commit = 2 //без этой строчки всё висло
Попробовал, у меня =2 прибило локальную базу данных так, что пришлось переустанавливать все заново
kkmspb Автор
18.09.2024 10:32А, что в битрикс нельзя установить чужой модуль из zip файла в админке? Надо только по ftp закачивать и распаковывать самому?
Добавить в репозиторий (маркетплейс) битрикс свой модуль - это реально?
w0lf
18.09.2024 10:32Можно загрузить zip файл через админку, через управление структурой, там же и распаковать.
Можно добавить модуль в Marketplace, мы это проходили, в принципе ничего сложного.
Aineko
Изучайте документацию по модулям.
модули из папки /local/modules/ нужно оформить в соответсвии с документацией, установить из админки и у них будет свой автолоад без модификации init.php
подписка на события у таких модулей происходит по другому - при установке самого модуля
https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=43&LESSON_ID=4809&LESSON_PATH=3913.3435.4609.4809
kkmspb Автор
Спс
kkmspb Автор
Чтобы модуль автоматом грузился надо, чтобы кто-то сделал includeModule. Автолоуд сам по себе не произойдет. Я пока нашел только вариант при установке модуля подписаться на событие например OnProlog и там в обработчике система вызовет includeModule.
Mausglov
Ваш подход мне кажется странным. Просто так подключение модуля не нужно, это лишняя нагрузка. Если в каком-то месте нужен функционал модуля, и есть событие в этом месте - регистрируете обработчик события. Событие произойдёт, модуль будет подключен.
kkmspb Автор
Да можно про OnProlog забыть и сразу подписаться на OnAdminSaleOrderViewDraggable (это как раз на странице заказа в админке) и тут и состав заказа полностью передается через параметр:
Хочу сказать, что в битрикс по факту можно обойтись одним модулем (и это гут), а в вордпрессе и джумле пришлось делать по 2 сущности.
thekingoftheworld
"Автолоуд" произойдет, если модуль установлен.
kkmspb Автор
Да теперь дошло. Именно так - в DoInstall.